16
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ブラウザからAmazon Cognitoのユーザーを切り替えるとLogins don't matchと怒られた

Last updated at Posted at 2017-12-29

経緯

amazon-cognito-identity-jsを使いブラウザからAmazon Cognitoで認証してDynamoDBにアクセスできるところまでを確認。
その後ログアウトして、別のユーザーでログインしようとしたところ次のエラーが発生した。

Logins don't match. Please include at least one valid login for this identity or identity pool

原因

AWS認証情報取得が成功する時のシーケンスはこんな感じ。ユーザー認証(Login)あたりは簡略化している。

Cognito Seq.png

エラーが発生した際はLoginの後にGetIdを行わずにGetCredentialsForIdentityを行って400(Bad Request)が返ってくる。

ではなぜGetIdが省略されてしまったのか?

amazon-cognito-identity-jsを使うとCognitoUsersignOut()を呼び出してもローカルストレージにはIdentityIdが残ったままである。そのため別ユーザーでLoginしてもIdentityIdが残っていると判断されてGetIdが省略されてしまう。

対処方法その1

AWS.CognitoIdentityCredentialsのコンストラクタの説明を見るとExamplesの中に次の記述がある。

// optional, only necessary when application runs in a browser
// and multiple users are signed in at once, used for caching
LoginId: 'example@gmail.com'

ブラウザで複数ユーザーがサインインする場合は必要だと書いている。。。

というわけで早速AWS.CognitoIdentityCredentialsの作成時にLoginIdを指定できるようにしてみる。

function createCognitoIdentityCredentials(session, loginId) {
    var params = {
        IdentityPoolId: 'ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
        LoginId: (loginId) ? loginId : undefined,
        Logins: {
            'cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxxxxx': session.getIdToken().getJwtToken();
        },
    };
    return new AWS.CognitoIdentityCredentials(params);
}

実際に動かすとLoginIdの有無でIdentityIdをローカルストレージに保存する際のKeyが変化する。

LoginId key
なし aws.cognito.identity-id.<identity_pool_id>
あり aws.cognito.identity-id.<identity_pool_id><LoginId>

IdentityIdを保存するKeyがユーザーごとにユニークになるため、ログインするユーザーが変わっても他人のIdentityIdを間違って使ってしまうことがなくなる。

例ではメールアドレスになっているけれど、ユーザーごとにユニークな値であれば問題ないと思われる。

対処方法その2

サインアウトしたのにローカルストレージにIdentityIdが残っているのが悪い!!!

ということで、CognitoIdentityCredentialsclearCachedId()をサインアウト時に呼び出すことでローカルストレージを綺麗にする。

function signOut() {
    var cognitoUser = userPool.getCurrentUser();
    if (cognitoUser != null) {
        if (AWS.config.credentials && AWS.config.credentials.clearCachedId) {
            AWS.config.credentials.clearCachedId();
        }
        cognitoUser.signOut();
    }
}

その1、その2のどちらかを行えばよい。両方を行ってもよい。

ライブラリのバージョン

ライブラリのバージョンによって差があるかもしれないので覚え書き。

    "amazon-cognito-identity-js": "^1.28.0",
    "aws-sdk": "^2.171.0",
16
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?