既存のアプリケーションから認証システムを切り離したい

まずは、パスワード管理をやめることと、SMSでの電話番号確認ができるようにする。

Amazon Cognito User Poolsを使う。最初の段階では、サーバーで Admin APIを使って既存の処理を置き換えていく。Admin APIには、AWSの認証情報が必要。

  • ユーザーの追加 : AdminCreateUser
  • サインイン : AdminInitiateAuth

User Pools について

Alias
  • サインインするときにUSERNAMEパラメーターに指定できる
  • 有効なaliasの調べ方
    • [email | phone_number]_verified=true
    • preferred_username の属性が有る
  • aliasとして使用する属性はuniqueでなくていいが、verified=trueのユーザーは1人だけ
    • ただし、preferred_usernameにはverified属性がないので、aliasにするならuniqueである必要がある
  • AdminCreateUserで既にあるユーザーと同じemailphone_numberを指定した場合
    • ForceAliasCreationがfalseまたは指定なし
      • UsernameExistsException
    • ForceAliasCreateがtrueの場合
      • すでにaliasとして有効だったユーザーの[email | phone_number]_verifiedがfalseになる
Verification
  • ユーザーの属性 email_verifiedphone_number_verified で管理されている。
  • [email | phone_number]_verified=trueのときのみがverified
  • admin APIでないとverified属性は書き込みできない
  • SetUserSettingでは書き込み許可がないのでunauthorizedエラー
verificationフロー
  • GetUserAttributeVerificationCode -> VerifyUserAttribute
  • 成功するとユーザー属性 email_verified=trueが設定される
  • 既にverified=trueであってもverificationフローは実行できる
    • 失敗してもtrueのまま
ユーザーの状態

docs.aws.amazon.com このページにある図がとてもわりやすい。

サインアップ
  • ユーザーによるユーザー登録 (サインアップ)
    • AWSの認証情報を持たなくてもユーザー登録ができる
      • clientIdだけで実行できる
        • client secretを発行していればsecretHashも必要になる
          • 登録されたユーザーを承認する方法
            • 管理者の承認
              • AdminConfirmSignUp
                • {Username, UserPoolId}
                • 確認コードなしでユーザーを確認する
                • “Confirms user registration as an admin without using a confirmation code”
                • ユーザーSign-upで"Registerd"のユーザーを"Confirmed"にする
            • SMS、EmailでのVerification
              • Varificationが選択されている場合、ユーザーがサインアップすると確認コードが自動的に送信さる

ユーザーを追加する

AdminCreateUser

必須の属性を指定しなくてもユーザーを作成できる。初回サインインのときに指定すればいい。 Verificationは自動では実行されない。

初期パスワードをInvitaion Messageでのみユーザーに知らせるのであれば[email | phone_number]_verified=trueと設定してしまえばいい。 Verification済みかどうかは、サインインしたときに属性[email | phone_number]_verified=trueで判断する。サインインしたあとであればいつでもVerificationフローを実行できる。

追加されたユーザーはForceChangePassword状態。初回ログイン時の認証チャレンジで新しいパスワードと足りない必須属性を与えるとConfirmedになる

管理者によるユーザー追加の場合は、verificationではなくてInvitation MessageをEmailまたはSMSで送信する。内容は、usernamepassword。テンプレートにpreferred_usernameは指定できなかった。

引数
  • DesiredDelivaryMediums
    • “EMAIL” | “SMS” | “EMAIL, SMS”
    • Invitationメッセージを送信する
  • ForceAliasCreation
    • このパラメータが無視されない条件
      • このリクエストで追加するユーザーの属性にaliasが含まれている
        • かつ phone_numberまたはemailの確認がtrue
          • aliasが既に別のユーザーの別名として存在する
    • trueの場合
      • 前のユーザーのaliasが新しく作成されたユーザーに移行される
      • 前のユーザーはそのaliasを使用してログインできなくなる
        • 前のユーザーはverified=falseが設定される
    • falseの場合
      • AliasExistsException
  • MessageAction
    • RESEND | SUPRESS | 指定しない
    • RESENDは既存ユーザーにInvitationを再送したいとき
      • 有効期限がリセットされる
  • UserAttributes
    • [email | phone_number]_verified=trueと設定できる
      • trueにしてもCognitoの動作は変らない。アプリケーションが値を見て判断する
  • ValidationData
    • Lambdaトリガーを使う場合に使用する

その他

  • SMSメッセージを送信する場合、Amazon SNSの使用制限の引き上げをリクエストする必要がある

  • client secret

    • SecretHash
    • これは送信元のAppを特定または限定するためのものか?
    • AccessTokenも開発者アカウントも必要ないAPI
      • ConfirmForgotPassword
      • ConfirmSignUp
        • Confirms registration of a user and handles the existing alias from a previous user.
        • {clientId, ConfirmationCode, ForceAliasCreation, Username, [SecretHash]}
        • SignUpのときに送信されたverification Code を引数にして、registrationをconfirmする
      • ForgotPassword
      • ResendConfirmationCode
      • SignUp
  • SRP

    • RFC2945
    • パスワードを送信するAPIで必要になる
    • “セキュアなバックエンドサーバー"ではSRPを使わずにパスワードをプレーンテキストとして送信できる
  • MFAとverification
    • MFAはユーザーがログインするときに、SMSで受け取った認証コードで確認をする
    • verificationはユーザー属性として指定された値が使用可能であるかを確認する
    • メッセージの種類
      • SMS
        • MFA認証
          • 認証コード 3分間
        • Phone Number Varification
          • 確認コード 24時間
        • invitation
          • Username, Password
      • EMail
        • EMail Verification
          • 確認コード 24時間
        • invitation
          • Username, Password
  • バイスの追跡
    • AdminInitiateAuthではサポートされていない
      • APIリファレンスには記載があるけどフォーラムに書いてあった
    • バイスをCognitoが記憶し、ユーザープール内のアプリケーションユーザーを関連付ける
      • なお、MFAを設定したときに記憶済みデバイスへのコード送信を止めることができる
    • ログイン->access_token -> confirmDevice -> DeviceKey
    • サインインしたデバイスには初回にデバイスキーとシークレットが割り当てられる
  • id_tokenとaccess_token
    • access_tokenはuser poolのユーザーのコンテキストでユーザー自身のプロパティ変更などに使う
      • SetUserSetting APIとか
  • 電話番号は頭に+81を付けて最初の0を除く
  • preferred_username
    • require, aliasの両方を選択することはできない
      • email、phone_numberはそれぞれ属性としてverifiedの値を持っている
      • aliasはverifiedでなければならない
      • requireはユーザーのステータスをconfirmにするために必要
      • preferred_usernameはverified属性を持たないので、値が設定されたことが即ちverified
      • confirmする前にverifiedできないから
    • aliasにした場合
      • updateUserAttributesを使用してverification
      • ログインに使用するIDだから、変更するときにはverificationが必要になる
    • If preferred_username is selected as an alias, the value can be provided only when an account is confirmed and it cannot be provided during registration.
      • aliasの場合は、registrationのときに設定できない?
        • adminCreateUserのときではなく、ユーザーによるsign-upのときの場合
          • adminCrateUserでは設定できる