見出し画像

Amazon Pinpointで楽々 ! 多要素認証機能の実装


今回のテーマ : 多要素認証


皆さま初めまして!TOPPANデジタル株式会社にて、AWS Top Engineersを目指しております井口と申します。
今回のテーマは、「多要素認証」です。
AWS サービスの内の一つ、「Amazon Pinpoint」を使って実装してみたので参考になれば幸いです。

そもそも多要素認証って何だ。という話から触れておきます。
多要素認証とは、認証の3要素である知識情報所持情報生体情報
うち、2つ以上を組み合わせて認証することを指します。

多要素認証イメージ

例えば上記添付画像では、
・「ユーザー名 / パスワードを知っている」という知識情報
・「携帯電話に送付されたコードを確認できる」という所持情報
の2つを組み合わせています。

現状 : AWSの多要素認証機能


AWSサービスを使って多要素認証機能を開発する際の選択肢は、以下が挙げられます。

  • Amazon cognitoの多要素認証設定

Amazon cognitoで多要素認証を設定するには、MFA(Multi-Factor Authentication)の強制という項目から容易に設定できます。

上記画像のように、AWSコンソール画面でAmazon cognitoユーザープールの設定を変更するだけです。MFAを必須にするを選択すると全ユーザーにMFAを求められます。また、オプションのMFAを選択すれば、特定のユーザーにだけMFA認証を求めることができます。
しかし、これは、Amazon cognitoでユーザー管理が必要になります。ユーザーをAmazon cognitoとは別で管理している場合、Amazon cognitoユーザープールの導入コストや、Amazon cognitoとデータベースの2重管理が生じてしまいます。

  • Amazon Pinpoint

そこで、Amazon Pinpointの出番となります。容易な設定で多要素機能を実装できます。

基本的な機能は、メッセージング機能として動作するAWSサービスです。
多要素認証として用いられる、ワンタイムパスワードの送付に対応しています。
中でも特筆すべき点は、他のメッセージングサービスと違って、多要素で使用したい設定が内包されている点です。細かい機能を開発しなくとも多様な設定を含んだワンタイムパスワードの送付が行えます。
・実装が容易である
・Amazon cognitoのようなユーザー管理は不要である
以上からAmazon Pinpointによる実装を選択しました。では、実装例をご紹介します。

検証 :  Amazon Pinpointを使った多要素認証機能


システム構成は以下です。3回APIを呼び出す形になっています。また、今回は管理者にだけ、多要素認証をかける構成で構築したため、管理者かどうかの判別をするAPIが含まれます。

システム構成図

API通信①では、管理者かどうかの判断を行います。
 入力値:ユーザーID
 出力値:true or false(管理者かどうか)
この出力を受けて、処理フローが変わります。

API通信②では、ワンタイムパスワード送付を行います。
 入力値:ユーザーID、電話番号
 出力値:ワンタイムパスワード送付状況
出力を受けて、次フローに行くか、エラーを出すか判断します。

入力値を受けたlambda関数では、Amazon Pinpointに
送信に必要な情報(どこに送る?、何桁のコード?、いつまで有効 etc…)
を入力してワンタイムパスワードを送付させます。

以下実装例です。(SDK for pythonを使っています)

def send_otp(PhoneNumber):
  client = boto3.client('pinpoint',region_name=region)
  destinationIdentity = PhoneNumber
  response = client.send_otp_message(
   ApplicationId = application_id,
   SendOTPMessageRequestParameters={
    'Channel': channel,
    'BrandName': brandname,
    'CodeLength': codelength,
    'ValidityPeriod': validityPeriod,
    'AllowedAttempts': allowedAttempts,
     'Language': language,
    'OriginationIdentity': originationIdentity,
    'DestinationIdentity': destinationIdentity,
    'ReferenceId': referenceId
   }
  )
  return response

sendOTPMessageRequestParameterに入力しているパラメータに送付情報が乗っています。

#パラメータ一覧======================================
#・application_id   :pinpointのプロジェクトID
#・channel       :pinpointで何を実行するか(今回はSMSを送信する)
#・brandname      :SMS上に表示するの送信者名
#・codelength     :otpの長さ
#・validityPeriod   :コードの有効期限
#・allowedAttempts   :入力を失敗できる回数
#・language       :言語
#・originationIdentity :送信元電話番号(pinpoint側で登録。送信者ID使用)
#・destinationIdentity :送信先電話番号(クライアントで入力された番号)
#・referenceId      :任意
#=================================================

API通信③では、ワンタイムパスワードの検証を行います。
 入力値:電話番号、ワンタイムパスワード
 出力値:検証結果
出力を受けて、ログイン完了とするか認めないか判断します。

入力値を受けたlambda関数では、Amazon Pinpointに
認証に必要な情報(どの番号?、どんなコード? etc…)
を入力してワンタイムパスワードの検証を行います。

以下実装例です。(SDK for pythonを使っています)

def verify_otp(destinationNumber,otp):
  client = boto3.client('pinpoint',region_name=region)
  response = client.verify_otp_message(
    ApplicationId = pin_pro_id,
    VerifyOTPMessageRequestParameters = {
      'DestinationIdentity': destinationNumber,
      'ReferenceId': referenceID,
      'Otp': otp
    }
  )
  return response

VerifyOTPMessageRequestParameterに入力しているパラメータに認証したい情報が乗っています。

#パラメータ一覧======================================
#・destinationIdentity :送信先電話番号(クライアントで入力された番号)【クライアント入力】
#・referenceId     :任意
#・otp         :確認したいotp                 【クライアント入力】
#====================================================


所感 :  使ってみて


Amazon Pinpointでの多要素認証機能ついて、スッキリ構築できるように感じました。特に、ワンタイムパスワードの制約を内包している点が非常に良いと思います。

  • Amazon cognito管理のユーザーリストでなくても使用できる

  • 多要素認証で求められる制約の実装が容易(入力回数制限、有効期限、失敗回数)

上記2点がAmazon Pinpointで実装するメリットかと思います。

〆:最後に


今回はAmaozn Pinpointを使って多要素認証を開発してみました。他にも、たくさんの実装パターンがあるので各々のサービスに適した手法で構築してきたいですね。
もっといろんなサービスを触り、最適な知見を蓄えていければと思います。その際はまた、記事として皆様にも発信していきます!
それでは、次回の記事もお楽しみに!