開発情報・ナレッジ

投稿者: SPIRERS ナレッジ向上チーム 2023年7月19日 (水)

SMSを利用した多要素認証を会員登録フローに実装する方法【絶対リーチ!SMS × SPIRAL ver.2】

会員サイトを作成した時、複数アカウントの作成や、なりすましを防ぐために多要素認証を実装したいケースがあるかと思います。
この記事では AI CROSS株式会社が提供する「絶対リーチ!SMS」を利用して、会員登録の際に多要素認証を実装する方法を解説します。
実際の設定方法やサンプルコードを記載しておりますので、ぜひ参考にしてみてください。

▼ SPIRALとSMSの連携について解説している関連記事もございますので、合わせてお読みいただければと思います。
2023年7月19日(水)
アプリの導入効果やセキュリティが向上するSMS活用例

仕様概要

フロー説明
1. 会員登録を行うとSMS認証ページのURLが記載されているメールが送付されます
2. SMS認証ページでSMS経由で送付されたコードを入力するとSMS認証が完了します
3. SMS認証を中断してしまった場合は、再開ページよりSMS認証を再開することができます
4. SMS認証完了後、ステータスが変更され会員サイトにログインできるようになります

会員登録の際にSMS認証を挟むことで、なりすましなどを防止することができます。
多要素認証を行ってセキュリティを高めたい場合や、複数アカウントの登録をして欲しくない場合に有効です。

①認証DBの設定

ログインする認証エリアを作成するため、認証DBを作成する必要があります。
SMS認証コードなどSMS認証に必要な下記の項目を追加するようにしてください。
必須項目
項目名 フィールドタイプ DB上で必須な属性 備考
会員ID テキスト 必須制約:あり
ユニーク制約:あり
認証IDとして利用するフィールドです。
※メールアドレスを認証IDとして利用する場合はこちらのフィールドは不要です。
パスワード パスワード 必須制約:あり
認証エリアにログインするのに必要なフィールドです。
メールアドレス メールアドレス 必須制約:あり
SMS認証ページURL記載のメールの送付先として必要なフィールドです。
※メールアドレスを認証IDとする場合はユニーク制約もありにしてください。
電話番号 電話番号 必須制約:あり
SMSの送信先として必要なフィールドです。
SMS認証コード テキスト 任意 SMSで送信する認証コードを格納するフィールドです。
SMS認証コード入力 テキスト 任意 SMS認証ページで認証コードを入力するためのフィールドです。
SMS認証フラグ セレクト 任意 SMS認証をしたかの管理をするためのフィールドです。
セレクト項目:1,未認証 2,認証済み
デフォルト値:1,未認証
レコードアクション設定
SMS認証コード発行やコード照合などはレコードアクションを使って実装します。

まずは、SMSで送信する認証コードを生成するトリガを設定してください。
登録トリガ
アクション名 アクション先 処理詳細
SMS認証コード生成 自DB 発動条件:設定しない
経路条件:フォームのみ
処理タイプ:更新

処理マッピング
アクション先DBフィールド:SMS認証コード
格納値:
RANDOM_NUM(6)

※ランダム6桁の数字を生成するように設定しています。こちらは変更しても構いません。

次に、SMS認証ページで入力された認証コードが正しいのか判定するためのトリガを設定してください。
認証エラーの場合はエラーページが表示され、認証に成功した場合は「SMS認証フラグ」のステータスを「認証済み」に変更します。
更新トリガ
アクション名 アクション先 処理詳細
SMS認証コード照合エラー 自DB 発動条件:
@SMS認証コード <> @SMS認証コード入力

経路条件:フォームのみ
処理タイプ:エラー
SMS認証コード照合サクセス 自DB 発動条件:
@SMS認証コード = @SMS認証コード入力

経路条件:フォームのみ
処理タイプ:更新

処理マッピング
アクション先DBフィールド:SMS認証フラグ
格納値:2(認証済み)

②会員登録ページの設定

認証DBにデータ登録するための会員登録ページを作成してください。
また登録フォームブロックを作成いただき、ページのbodyタブに設置してください。

簡単にデザインを当て込みたい場合は以下の特集を参考にしてください。
上の画像ではコピペCSSの「シンプルモダン」を使用しています。

2022年11月9日(水)
デザイン系特集
メールアクション設定
登録フォームブロックのメールアクションにSMS認証のためのメールを設定してください。
文面は自由ですが必ずこの後作成する「⑤SMS認証ページ」のクリックログインURLを記載するようにしてください。
また、セキュリティの観点からクリックログインURLの有効期限を15分に設定するようにしてください。

③SMS認証再開ページの設定

「⑤SMS認証ページ」のクリックログインURLは有効期限を15分に設定するため、SMS認証完了せずに離脱してしまうと会員サイトにログインできません。
会員IDで照合可能な認証復帰用のレコード照合ブロックを設置した、一般公開ページを作成してください。
照合成功メール設定
レコード照合ブロックにはレコード照合が成功した際に送信される照合成功メールが設定できます。
照合成功メールの文面内に「②会員登録ページ」登録フォームブロックに設定したメールアクションと同じく「⑤SMS認証ページ」のクリックログインURLを記載するようにしてください。
※有効期限も同じように15分に設定するようにしてください。

最後に作成したレコード照合ページのURLは「②会員登録ページ」登録フォームブロックに設定したメールアクションの文面内に記載してください。

④SMS認証エリアの設定

SMS認証用のクリックログイン認証エリアを作成します。
セキュリティを高めるためにセッション有効期限は15分で設定してください。

⑤SMS認証ページの設定

SMSに送信された認証コードを入力するためのページをSMS認証エリア内に作成します。
SMS認証ページに関してはトップページを利用してください。

また認証コードを入力する更新フォームブロックをページのbodyタブに設置してください。
更新フォームブロックは認証エリアを作成した際に自動で作成されるものを流用するか、新規で作成するようにしてください。
ページ内には、この後作成する「⑥SMS再送信ページ」のリンクも必ず付けるようにしてください。

初回のページアクセス時に認証コードをSMS送信するプログラムが必要となります。
ページのPHPタブに下記のコードを貼り付けて作成してください。
PHPタブ
<?php
define("TOKEN","XXXX");
define("CLIENT_ID","XXXX");
define("SMS_CODE","XXXX");
define("MESSAGE","SMS認証コード:");
define("AUTH_ID", $SPIRAL->getAuthRecordByFieldId("XX"));
define("PHONE_NUMBER", $SPIRAL->getAuthRecordByFieldId("XX"));
define("SMS_AUTH_CODE", $SPIRAL->getAuthRecordByFieldId("XX"));
define("SMS_FLAG", $SPIRAL->getAuthRecordByFieldId("XX"));
define("CLICK_LOGIN", $SPIRAL->getParam("cl"));

if (SMS_FLAG[1] == "1" && CLICK_LOGIN != null) {
    $url = 'https://sms-api.aossms.com/p5/api/mt.json';

    $data = array(
        'token' => TOKEN,
        'clientId' => CLIENT_ID,
        'smsCode' => SMS_CODE,
        'message' => MESSAGE. SMS_AUTH_CODE,
        'phoneNumber' => PHONE_NUMBER,
        'clientTag' => AUTH_ID. CLICK_LOGIN,
    );
    $data = http_build_query($data, "", "&");

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    curl_close($ch);
    $response = json_decode($response , true);
}
?>
また、コード内の設定値に以下のように値を設定してください。
設定値
TOKEN SMS送信APIのアクセスキーとして使用するトークンを設定します。
「絶対リーチ!SMS」管理画面のアカウント情報から値を確認してください。
CLIENT_ID SMS送信APIでパラメータとして必須となる契約クライアントIDを設定します。
「絶対リーチ!SMS」管理画面のクライアント情報から値を確認してください。
SMS_CODE SMS送信APIでパラメータとして必須となるSMSコードを設定します。
「絶対リーチ!SMS」管理画面のクライアント情報から値を確認してください。
MESSAGE SMSで送信するメッセージを設定します。
サンプルではここに設定した文面と「SMS認証コード」を送信しています。
※要件に合わせてメッセージは適宜変更するようにしてください。
AUTH_ID XX に「会員ID」のフィールドIDを設定してください。
PHONE_NUMBER SMSの送信先となる電話番号を設定します。
XX に「電話番号」のフィールドIDを設定してください。
SMS_AUTH_CODE SMS経由で送信する認証コードを設定します。
XX に「SMS認証コード」のフィールドIDを設定してください。
SMS_FLAG SMS認証ステータスを判断するフラグを設定します。
XX に「SMS認証フラグ」のフィールドIDを設定してください。
CLICK_LOGIN クリックログインURLのパラメータの値を取得して設定しています。
ページ遷移時に初回のみSMS送信する制御に利用しています。
※値は変更しないでください。

以上で、SMS認証ページの設定は完了です。

⑥SMS再送信ページの設定

次に万が一SMSメッセージが正しく受け取れなかった場合に、再送信を行うことができるページを同じくSMS認証エリア内に作成します。

SMS送信が失敗した際にエラーを出力するためのタイムリーフをページのbodyタブに記載してください。
エラーメッセージはPHP側で設定しておりデフォルトでは「エラーが発生したか、すでにSMS認証が済んでいます。」と表示されます。
bodyタブ
<div>
    <div th:if="${cp.result.isSuccess}">
        <div th:text="${cp.result.value['API_RESPONSE']}"></div>
    </div>
    <div th:if="${!cp.result.isSuccess}">
        <div th:text="${cp.result.errorMessage}"></div>
    </div>
</div>
再送信処理実行後、SMS認証ページにリダイレクトする処理をページのheadタブに記載してください。
headタブ
<meta http-equiv='refresh' th:if="${cp.result.value['REDIRECT']}" th:content="|0; URL=${cp.result.value['REDIRECT']}|" />
認証コードをSMS送信するプログラムをページのPHPタブに貼り付けてください。
PHPタブ
<?php
define("TOKEN","XXXX");
define("CLIENT_ID","XXXX");
define("SMS_CODE","XXXX");
define("MESSAGE","SMS認証コード:");
define("PHONE_NUMBER", $SPIRAL->getAuthRecordByFieldId("XX"));
define("SMS_AUTH_CODE", $SPIRAL->getAuthRecordByFieldId("XX"));
define("SMS_FLAG", $SPIRAL->getAuthRecordByFieldId("XX"));
define("REDIRECT_PATH", "XXXX");

$SPIRAL->setTHValue("API_RESPONSE", "エラーが発生したか、すでにSMS認証が済んでいます。");
$SPIRAL->setTHValue("REDIRECT", null);

if (SMS_FLAG[1] == "1") {
    $url = 'https://sms-api.aossms.com/p5/api/mt.json';

    $data = array(
        'token' => TOKEN,
        'clientId' => CLIENT_ID,
        'smsCode' => SMS_CODE,
        'message' => MESSAGE. SMS_AUTH_CODE,
        'phoneNumber' => PHONE_NUMBER,
    );
    $data = http_build_query($data, "", "&");

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    curl_close($ch);
    $response = json_decode($response , true);
    if ($response["responseCode"] == 0) {
        $SPIRAL->setTHValue("API_RESPONSE", "");
        $SPIRAL->setTHValue("REDIRECT", REDIRECT_PATH);
    }
}
?>
また、コード内の設定値に以下のように値を設定してください。
設定値
TOKEN SMS送信APIのアクセスキーとして使用するトークンを設定します。
「絶対リーチ!SMS」管理画面のアカウント情報から値を確認してください。
CLIENT_ID SMS送信APIでパラメータとして必須となる契約クライアントIDを設定します。
「絶対リーチ!SMS」管理画面のクライアント情報から値を確認してください。
SMS_CODE SMS送信APIでパラメータとして必須となるSMSコードを設定します。
「絶対リーチ!SMS」管理画面のクライアント情報から値を確認してください。
MESSAGE SMSで送信するメッセージを設定します。
サンプルではここに設定した文面と「SMS認証コード」を送信しています。
※要件に合わせてメッセージは適宜変更するようにしてください。
PHONE_NUMBER SMSの送信先となる電話番号を設定します。
XX に「電話番号」のフィールドIDを設定してください。
SMS_AUTH_CODE SMS経由で送信する認証コードを設定します。
XX に「SMS認証コード」のフィールドIDを設定してください。
SMS_FLAG SMS認証ステータスを判断するフラグを設定します。
XX に「SMS認証フラグ」のフィールドIDを設定してください。
REDIRECT_PATH SMS認証ページのURLを相対パスで設定してください。
SMS再送信ページからSMS認証ページにリダイレクトするために使用しています。
例)/smsAuthArea

以上で、SMS再送信ページの設定は完了です。

⑦会員認証エリアの設定

会員用の認証エリアを作成し、認証方法はID/パスワードで設定します。
SMS認証が済んでいない場合はログインを拒否するために、ログイン制限を「制限する」に設定してください。
設定は「SMS認証フラグ 等しい 認証済み」とすることで認証済みステータスの会員のみログインできるようになります。
また、会員認証エリアのログインページURLは「⑤SMS認証ページ」の完了ステップに記載してください。

その他の認証エリア内ページは要件に合わせて適宜追加するようにしてください。

[EX]削除バッチの設定

会員登録してもSMS認証を最後まで行わなわずに放置されてしまった会員IDは、不要なデータとして残り続けます。
また、一度登録した会員IDは再度登録することができないため、定期的に不要データを削除する削除バッチを設定してください。
削除バッチはスケジュールトリガとカスタムプログラムアクションを利用して設定することが可能です。

削除はAPIのレコード一括削除依頼作成(batch)を使用して行ってください。
コードは以下の記事を参考にしていただければと思います。

2022年9月30日(金)
APIメソッドごとのサンプルコードまとめ Record (batch)

レコード一括削除依頼作成メソッドでは、リクエストボディに抽出条件(where)を指定することで、削除するレコードを指定することができます。
抽出条件を以下のように設定することで、登録から一週間過ぎているかつSMS認証フラグが未認証のものを抽出して削除可能です。
抽出条件(where)
?where=@_createdAt<DATE_TIME(NOW())-INTERVAL('1weeks')AND@SMS認証フラグ=1
以上のようにして、毎日スケジュールトリガを動作させるように設定すると、登録から一週間経ってもSMS認証されていないデータを自動で削除できるようになります。

[EX2]フォームの完了ステップでSMS送信する方法

SMSを多要素認証での利用ではなく、フォーム登録完了後のサンクスメールの代わりに利用したいケースもあるかと思います。
その際に利用できる完了ステップでSMS送信するためのサンプルコードを作成しましたので参考にしていただければと思います。

登録フォームページのPHPタブに以下のコードを記載してください。
こちらコードを記載することで登録フォームブロックの完了ステップでSMS送信することができるようになります。
PHPタブ
<?php
define("TOKEN","XXXX");
define("CLIENT_ID","XXXX");
define("SMS_CODE","XXXX");
define("MESSAGE","XXXX");
define("PHONE_FIELD", "XXXX");
define("REGIST_FORM", "XXXX");

$registForm = $SPIRAL->getRegistrationForm(REGIST_FORM);
$completed = $registForm->isCompletedStep();

if ($completed) {
    $url = 'https://sms-api.aossms.com/p5/api/mt.json';
    $record = $SPIRAL->getRecordValue();
    $phoneNumber = preg_replace("/(-| | )/", "", $record["item"][PHONE_FIELD]);

    $data = array(
        'token' => TOKEN,
        'clientId' => CLIENT_ID,
        'smsCode' => SMS_CODE,
        'message' => MESSAGE,
        'phoneNumber' => $phoneNumber,
    );
    $data = http_build_query($data, "", "&");

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    curl_close($ch);
    $response = json_decode($response , true);
}
?>
また、コード内の設定値に以下のように値を設定してください。
設定値
TOKEN SMS送信APIのアクセスキーとして使用するトークンを設定します。
「絶対リーチ!SMS」管理画面のアカウント情報から値を確認してください。
CLIENT_ID SMS送信APIでパラメータとして必須となる契約クライアントIDを設定します。
「絶対リーチ!SMS」管理画面のクライアント情報から値を確認してください。
MESSAGE SMSで送信するメッセージを設定します。
最大で660文字までのメッセージを設定することが可能です。
※全角/半角問わず文字数でカウントされます。
PHONE_FIELD SMSの送信先となる電話番号フィールドの識別名を設定してください。
REGIST_FORM 登録フォームブロックの識別名を設定してください。

最後に

SMSを利用した多要素認証やメッセージ送信の実装方法を解説いたしました。
実際に設定した後は動作確認を必ず行い、動作に問題がないか確認をしてください。

不具合やほかのやり方が知りたい等あれば、下記の「コンテンツに関しての要望はこちら」からご連絡ください。
解決しない場合はこちら コンテンツに関しての
要望はこちら