简体   繁体   中英

AWS Amplify Auth with Cognito User Pool not returning nonce or at_hash claim in JWT id_token

I'm trying to use Amplify Auth to implement an OpenID Connect Implicit Flow to provide SSO to a number of React clients.

I've been able to get this working with Cognito Hosted UI, but that requires other apps users to click a button to confirm login in order to authenticate. I'd prefer for it to be seamless ie when a user is logged in on one site and navigate to another they are automatically authenticated if they have a session with the auth provider.

To try and achieve this I've set up a separate Amplify app that uses the React Authenticator Component.

I'm able to authenticate with this and redirect back to the client. However the id_token doesn't contain the at_hash or nonce claim. Presumably, the at_hash is missing because the authentication provider app is not sending the responseType of token id_token when it authenticates with Cognito. The nonce is missing because I haven't found a way to pass it in.

  1. Is there a way to get Amplify Authenticator SignIn to request an id_token with the at_hash claim?

  2. Is it possible to pass a nonce value through to the id_token claims?

Note I'm trying to adhere to: https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowSteps Specifically for this part: 3.2.2.10. ID Token

import React from 'react';
import { Authenticator, ConfirmSignIn, SignIn } from 'aws-amplify-react';
import Amplify, { Auth } from 'aws-amplify';
import awsconfig from './aws-exports';

Amplify.configure(awsconfig);

const getSearchParams = () =>
    window.location.search.substr(1);

const getValueFromSearchParam = (key) =>
    new URLSearchParams(getSearchParams()).get(key);

const getRedirectUri = () => {
    const redirect_uri = getValueFromSearchParam('redirect_uri');
    return redirect_uri ? decodeURI(redirect_uri) : null;
};

const Login = () => {
    const handleAuthStateChange = (state) => {
        if(state === 'signedIn') {
            const redirect_uri = getRedirectUri();
            const state = getValueFromSearchParam('state');
            if(redirect_uri === null) {
                throw new Error('No redirect_uri provided');
            }
            Auth.currentSession().then(currentSession => {
                const id_token = currentSession.idToken.jwtToken;
                const access_token = currentSession.accessToken.jwtToken;
                const redirect = `${redirect_uri}#access_token=${access_token}&id_token=${id_token}&state=${state}`;
                window.location.replace(redirect);
            }).catch(err => console.error(err));
        }
    };

    return (
        <Authenticator
            hideDefault={true}
            onStateChange={handleAuthStateChange}
        >
            <SignIn  />
            <ConfirmSignIn/>
        </Authenticator>
    );
};

A few issues here that may be of interest:

  • Cognito lacks some standards based support, as you are noticing
  • If you use response_type = token id_token you will be limited to fixed 60 minute user sessions
  • Amplify may not be the most standard based library in terms of nonce parameters etc
  • Authorization Code Flow (PKCE) is recommended these days for SPAs - you may find this an easier way to implement the post login checks you are looking for

Unfortunately you may need to make some trade offs when working with Cognito - and make the 'least bad choice'. If it helps, here is some stuff of mine to compare against:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM