読者です 読者をやめる 読者になる 読者になる

ぱんだのびぼーろく

わたしの備忘録、生物学とプログラミングが多いかも

cognitoでログイン/セッション管理

AWS javascript web プログラミング

ユーザーを限定するwebサイト・webアプリはログインの仕組みが必要になる.
AWS cognito, 特にUser Poolsの機能でこれが実装できる.

Cognitoとは何ぞ?という方はこちら一読を推奨.
tarepan.hatenablog.com

Cognitoを用いたセッション管理の大枠

  • インターネットを介した初回認証、認証情報のローカル (ブラウザ) への保存
  • 各webページ/アプリ遷移でローカル認証情報のチェック、不正ならトップページ/ログイン画面へ強制リンク

初回認証時のデータがローカルへ自動保存され、必要に応じてページ遷移時などに読み出し関数でそれをチェック (validation)、未ログイン・期限切れ等の場合はそのページから追い出す.
AWS Cognito UserPoolsを利用すれば、関数を数個叩くだけでこの仕組みが実装できる, すごいぞ Amazon.

詳細

  • JWT (Json Web Token)
  • 認証フロー

の知識があると良い。
認証時にlocalStorageへJwtTokenをセットし、"その後"はgetSessionでtokenの取り出し・利用期限のvalidationする。不正な場合はgetSessionのcallback内でログインページへ飛ばす.
"その後"ではネットワークを介したチェックはしてなさそう.
ログアウト時にはlocalStorageとsession変数を空にしてる.

初回 : ネットワーク介した認証
2回目以降 : localStorageのtokensをvalidationして許可

ユーザー認証とページをまたいだログインの重要コード

UserPoolインスタンスの作成

new CognitoIdP.CognitoUserPool(data)

  • @param {object} data / Creation options.
    • @param {string} data.UserPoolId / Cognito user pool id.
    • @param {string} data.ClientId / User pool application client id.
    • @param {int} data.Paranoia / Random number generation paranoia level.

CognitoUser.authenticateUser

内部でauthRequest (CognitoIdPネイティブ関数) を叩き、所定の認証プロセスを通過したら

  • signInUserSessionへのセット
  • localStorageへのcache

を実行

// amazon-cognito-identity-js/src/CognitoUser.js
// most important: line 225 - 227
export default class CognitoUser {
    ... 
    authenticateUser(authDetails, callback) {
        ... 
        this.client.makeUnauthenticatedRequest('initiateAuth', {
            ...
        }, (err, data) => {
            ... 
            this.client.makeUnauthenticatedRequest('respondToAuthChallenge', {
            ...}, (errAuthenticate, dataAuthenticate) => {
                ...
                this.signInUserSession = this.getCognitoUserSession(dataAuthenticate.AuthenticationResult);
                this.cacheTokens();
                ...
            });
        });
}}

// line 77
    constructor(data){
        ... 
        this.client = data.Pool.client;
    }


// amazon-cognito-identity-js/src/CognitoUserPool.js
export default class CognitoUserPool {
    ... 
    constructor(data) {
        ... 
        this.client = new CognitoIdentityServiceProvider({ apiVersion: '2016-04-19', region });
}}

getCurrentUser

CognitoUserPool.getCurrentUser()
最後に認証したユーザー名をlocalStorageから取り出し、CognitoUserにして返す.いない場合はnull.
localStorageへの登録タイミングは CognitoUser.cacheToken() 実行時のみ.
実行タイミングは CognitoUser.authenticateUser() のみ.

()=>CognitoUser(LastAuthUser)

// amazon-cognito-identity-js/src/CognitoUser.js
// important: line 788 - 800
export default class CognitoUser {
    ... 
    cacheTokens() {
        const keyPrefix = `CognitoIdentityServiceProvider.${this.pool.getClientId()}`;
        ... 
        const lastUserKey = `${keyPrefix}.LastAuthUser`;
        ... 
        storage.setItem(lastUserKey, this.username);
    }
    ... 
}

getSession

validなtokensを検出した場合にcallbackが実行される.
cognitoUser.getSession(callback)
callback: (err, signInUserSession)=>{}
cognitoUserにvalidなsignInUserSessionがあれば即callback実行.
ない場合はユーザー名をもとにlocalStorageからtokenを取得、CognitoUserSessionに入れ、validならcallback実行.
期限切れ (invalid) ならrefreshTokenを用いて取得し直し、その後 callback.
他の場合はErrorでcallback実行.

CognitoUserSession

IdToken, AccessToken, RefreshTokenの入れ物. validation check関数 (isValid) を実装.

AWS Cognito Identityとの関係

ユーザー登録・ログイン・セッション管理は (基本的に) User Pools上で完結する.
Identity PoolやFederated Identityの仕組みは、他のAWS resourceへのアクセス等に必要になる.

amazon-cognito-identity-js

全ては解決した。amazon-cognito-identity-js は AWS.CognitoIdenitityServiceProviderをメソッド追加で拡張している。

参考

Integrating User Pools with Amazon Cognito Identity - Amazon Cognito

github.com