---
title: ログイン画面に2段階認証を実装する
description: Kurocoのログインのエンドポイントには2段階認証を実装するためのパラメータの準備があり、Email, Authenticator, SMSによる2段階認証を容易に実装できます。
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

## 概要
Kurocoのログインのエンドポイントには2段階認証を実装するためのパラメータの準備があり、Email, Authenticator, SMSによる2段階認証を容易に実装できます。

本チュートリアルでは3つの認証方法による2段階認証のログイン動作を確認し、それを利用したフロントエンドのコードを紹介します。

### 学べること
以下の手順でログイン画面に2段階認証を実装します。

- [2段階認証の動作を確認する](#2段階認証の動作を確認する)
  - [Emailによる2段階認証](#emailによる2段階認証)
  - [Authenticatorによる2要素認証](#authenticatorによる2要素認証)
  - [SMSによる2要素認証](#smsによる2要素認証)
  - [追加認証の強制](#追加認証の強制)
- [フロントエンドの実装をする](#フロントエンドの実装をする)

### 前提条件
このページは、KurocoとNuxt.jsでのプロジェクトが構築済みであることを前提としています。  
まだ構築していない場合は、下記のチュートリアルを参照してください。  

:::info
- [Kurocoビギナーズガイド](/ja/docs/tutorials/beginners-guide/)   
:::

:::info
本チュートリアルでは以下のバージョンでコードを書いています。  
Nuxt2: v2.15.8  
Nuxt3: v3.8.0  
:::

:::tip
本ドキュメントではCookie認証による設定の流れを説明します。  
動的アクセストークンを利用する場合は、[動的アクセストークンの場合の認証方法](#動的アクセストークンの場合の認証方法)も参照してください。
:::

## 2段階認証の動作を確認する
### Emailによる2段階認証
#### エンドポイントの作成
任意のAPIで「新しいエンドポイントの追加」をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/0da1dd80f2c46ce371589890a4612c72.png)

以下の設定をします。

|項目|設定内容|
|:--|:--|
|パス|2steplogin/email|
|カテゴリー|認証|
|モデル|Login|
|オペレーション|login_challenge |
|twofactor_method|email|

![Image from Gyazo](https://t.gyazo.com/teams/diverta/799a76348ad775d91cb7d4169f60911d.png)

設定ができたら[追加する]をクリックしてエンドポイントを追加します。

#### SwaggerUIで動作の確認
対象のAPIから[Swagger UI]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/b2611950c27f7c5808551da8664384a9.png)

追加したエンドポイントを開き[Try it out]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/ca5ef0830be1223d9a285a40bc52e94b.png)

認証情報を入力して[Execute]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/c71335322e93cddb21ff6f320c6699c3.png)

正しい認証情報が入力された場合は「追加の認証情報が必要です。」のレスポンスが返ります。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/e85c7f3b5782b1ac4ac92a1f30afa6b6.png)

ユーザーのメールアドレス宛に認証コードが届きます。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/edc90af9660f4ebfbe9f973700f6b03c.png)

:::tip
通知の内容は`login/authentication_code`の[メッセージひな形](/ja/docs/management/email-template/)で編集可能です。
:::

Request bodyから`password`を削除し、`onetime_password`を入力して再度[Execute]をクリックします。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/c314191a75a617ec071a1084cffa12cb.png)

grant_tokenが発行され、ログインできたことを確認できました。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/dd1022c33fc898a8fb93a9f6f1b53355.png)

### Authenticatorによる2要素認証
Authenticatorによる2要素認証を利用するには、まずKurocoの管理画面でワンタイムパスワードを設定する必要があります。  

#### ワンタイムパスワードの利用設定をする

[環境設定] -> [サイト一覧]をクリックします。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/6e62d36fc06738d5bd8bde2772e0d807.png)

ログインの項目のワンタイムパスワードを[利用する]に設定します。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/782b5eb20e42fc14840edf327cce67da.png)

#### ワンタイムパスワードを登録する

[メンバー管理]->[メンバー]から自身のメンバー情報に遷移するか、管理画面右上のアイコンから自身のメンバー情報に遷移します。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/c6a612079b1f9b09d4fde7f7716c73f6.png)

ID情報タブからワンタイムパスワードの[設定する]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/2d7a5b20595ef61281e73dda3e6ec486.png)

ワンタイムパスワードの設定画面が開くので、[登録する]をクリックします。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/74c042c775907c2278de2f102c9eafe5.png)

Google Authenticatorのアプリを開き、QRコードを読み込み、6桁の認証コードを入力します。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/d5cff2ee8efceb36ef73380c48370d52.png)

登録しました。の表示が出たら設定は完了です。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/1e20fc4dd62251782ecf9d02f335cb95.png)

#### エンドポイントの作成
ワンタイムパスワード利用の準備ができたら、任意のAPIで「新しいエンドポイントの追加」をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/0da1dd80f2c46ce371589890a4612c72.png)

以下の設定をします。

|項目|設定内容|
|:--|:--|
|パス|2steplogin/code|
|カテゴリー|認証|
|モデル|Login|
|オペレーション|login_challenge |
|twofactor_method|code|

![Image from Gyazo](https://t.gyazo.com/teams/diverta/2448e8c93c44bbd1872be34755fb64c8.png)

設定ができたら[追加する]をクリックしてエンドポイントを追加します。

#### SwaggerUIで動作の確認
対象のAPIから[Swagger UI]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/b2611950c27f7c5808551da8664384a9.png)

追加したエンドポイントを開き[Try it out]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/7d730d8c789bde559491c22747e7ff2a.png)

認証情報を入力して[Execute]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/c71335322e93cddb21ff6f320c6699c3.png)

正しい認証情報が入力された場合は「追加の認証情報が必要です。」のレスポンスが返ります。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/e85c7f3b5782b1ac4ac92a1f30afa6b6.png)

端末からGoogle Authenticatorのアプリを開き認証コードを確認します。  

Request bodyから`password`を削除し、`onetime_password`を入力して再度[Execute]をクリックします。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/839b935ef021e42c6e7941fe5c830dbe.png)

grant_tokenが発行され、ログインできたことを確認できました。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/dd1022c33fc898a8fb93a9f6f1b53355.png)

### SMSによる2要素認証
SMSによる2要素認証を利用するには、Twilioとの連携が必要です。  
また、メンバー情報の電話番号に"090","080","070","060"から始まる日本国内の電話番号が登録されている必要があります。  
始めに、以下のドキュメントを参考に設定をしてください。  

:::info
[Twilioと連携してSMSを送信する](/ja/docs/tutorials/how-to-connect-to-twillio/)
:::

#### エンドポイントの作成
SMS利用の準備ができたら、任意のAPIで「新しいエンドポイントの追加」をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/0da1dd80f2c46ce371589890a4612c72.png)

以下の設定をします。

|項目|設定内容|
|:--|:--|
|パス|2steplogin/sms|
|カテゴリー|認証|
|モデル|Login|
|オペレーション|login_challenge |
|twofactor_method|sms|

![Image from Gyazo](https://t.gyazo.com/teams/diverta/3de90680b6aa1174ff261888dbf2ec28.png)

設定ができたら[追加する]をクリックしてエンドポイントを追加します。

#### SwaggerUIで動作の確認
対象のAPIから[Swagger UI]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/b2611950c27f7c5808551da8664384a9.png)

追加したエンドポイントを開き[Try it out]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/7a1385323d255fa212e5c0c9c5ff2de9.png)

認証情報を入力して[Execute]をクリックします。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/c71335322e93cddb21ff6f320c6699c3.png)

正しい認証情報が入力された場合は「追加の認証情報が必要です。」のレスポンスが返ります。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/e85c7f3b5782b1ac4ac92a1f30afa6b6.png)

SMSで認証コードが届きますので値を確認します。  

:::tip
通知の内容は`login/sms_authentication_code`の[メッセージひな形](/ja/docs/management/email-template/)で編集可能です。
:::

Request bodyから`password`を削除し、`onetime_password`を入力して再度[Execute]をクリックします。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/c314191a75a617ec071a1084cffa12cb.png)

grant_tokenが発行され、ログインできたことを確認できました。
![Image from Gyazo](https://t.gyazo.com/teams/diverta/dd1022c33fc898a8fb93a9f6f1b53355.png)

### 追加認証の強制
追加の認証情報が登録されていない場合は`twofactor_method`のパラメータが設定してあってもログインが成功します。  
ログイン後に電話番号等を登録させることを想定していますが、ログインをさせずにエラーを出したい場合はカスタム処理を作成し、[後処理](/ja/docs/reference/post-processing/)に設定することで対応してください。  

以下は追加の認証情報のステップを通さずにログインが完了した場合に、強制ログアウトし、エラーのレスポンスを出す後処理の例です。  

```smarty
{if isset($smarty.post.password) && $json.grant_token != null}
    {append var=json.errors value='追加の認証情報が登録されていません。'}
    {logout}
{/if}
{assign var=processed_json value=$json}
```

![Image from Gyazo](https://t.gyazo.com/teams/diverta/7b1b6f6a08625b5edabc8e1648f33bde.jpg)

## フロントエンドの実装をする
最後に、SwaggerUIで確認した動作をフロントエンドで実装します。  

`/login/2step_login/`のディレクトリにindex.vue のファイルを作成します。  
以下はEmailを利用した2段階認証の例です。

<Tabs>
<TabItem value="Nuxt2" label="Nuxt2" default>

```markup reference title="/pages/login/2step_login/index.vue"
https://github.com/diverta/kuroco-documents/blob/main/sample_code/front-end/nuxtjs/2step_login_email.vue
```

</TabItem>
<TabItem value="Nuxt3" label="Nuxt3" default>

```markup reference title="/pages/login/2step_login/index.vue"
https://github.com/diverta/kuroco-documents/blob/main/sample_code/front-end/nuxt3/2step_login_email.vue
```

</TabItem>
</Tabs>

:::caution
上記サンプルのサンプルは参考のため最低限のコードになっています。  
実際に利用する際には、フォームのバリデーション処理や、`@nuxt/auth` などのライブラリもご利用ください。
:::

:::caution
`/rcms-api/1/2steplogin/email`の部分はご自身のエンドポイントのURLに変更してください。
:::

#### 動作確認
実行し、動作確認ができたら、ログイン画面への2段階認証の実装は完了です。

![Image from Gyazo](https://t.gyazo.com/teams/diverta/2a1cb8861b4163891da71334dd29ceb2.gif)

## 動的アクセストークンの場合の認証方法

動的アクセストークンを利用する場合、2段目の認証に Login::login_challenge_mfa のエンドポイントを使用します。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/c4b1c69da835f68c0d44c8a8e8617754.png)

アクセストークン取得までの流れは以下のようになります。

1. Login::login_challengeのエンドポイントにemail/passwordをPOSTし、mfa_access_tokenを取得する
  ![Image from Gyazo](https://t.gyazo.com/teams/diverta/c63e33fdcffbe4fab65d983be75a74b4.png)
2. Login::login_challenge_mfa のエンドポイントに以下のリクエストを送り、grant_tokenを取得する  
    - mfa_access_tokenをX-RCMS-API-ACCESS-TOKENのヘッダーに含める
    - Request bodyにonetime_passwordを含める

  ![Image from Gyazo](https://t.gyazo.com/teams/diverta/5f0be5a9dfddd5b56615086dc93e1027.png)
3. grant_tokenをLogin::token のエンドポイントにPOSTするとアクセストークンが取得できる

## 関連ドキュメント
- [Kurocoビギナーズガイド](/ja/docs/tutorials/beginners-guide/)  
- [KurocoとNuxt.jsで、ログイン画面を構築する](/ja/docs/tutorials/integrate-login/)
- [後処理](/ja/docs/reference/post-processing/)
- [KurocoとNuxt.jsで、会員登録画面に2段階認証を実装する](/ja/docs/tutorials/implementing-two-step-verification-on-registration-form/)