AWS API Gateway Authorizer works with Cognito HostedUI but not with access_token from amazon-cognito-identity-js

850 Views Asked by At

When I use the Cognito HostedUI, I receive the access_token from URL parameters in callback page and feed it to my API call header as follows:

new HttpHeaders({
    'Content-Type': 'application/json',
    Authorization: access_token // received from callback URL parameters
});

And it works fine. But due to the limitations of HostedUI design, I implemented a custom login/logout logic using this tutorial

Since amazon-cognito-identity-js requires an App Client without a Client Secret, I created a new App Client. So now I have two. (Not sure if it causes any problems)

The simplified partial code looks like the following:

let authenticationDetails = new AuthenticationDetails({
    Username: this.email_address, // user input
    Password: this.password // user input
});
let poolData = {
    UserPoolId: environment.cognitoUserPoolId,
    ClientId: environment.cognitoAppClientId
};
let userPool = new CognitoUserPool(poolData);
let userData = { Username: this.email_address, Pool: userPool };
var cognitoUser = new CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: (result: any) => {
    console.log(result);
    const access_token = result.getAccessToken().getJwtToken(); // getting access_token
    if (!access_token) {
    alert('User token is not found. Please sign in again.');
    return;
    }
...

Now this let's me Login and Logout successfully, and I get the user's detailed information. But when I feed this access_token to API Authorization header I always get error 401 Unauthorized error. I even tried using id_token and the refresh_token, nothing works.

All my Cognito, API Gateway, S3, Lambda etc. settings are same as before. So why do I keep getting a 401 error? Maybe I am missing a IAM permission? Any help would be appreciated.

UPDATE:

I noticed the access_token from HostedUI callback has:

"scope": "aws.cognito.signin.user.admin phone openid profile email"

Even though in Cognito AppClient settings I have selected all 5 OpenID Connect scopes, the access_token in amazon-cognito-identity-js response has only:

scope: "aws.cognito.signin.user.admin"

In each API request OAuth Scopes option I have "email". So this seems to be the problem. Should I add "aws.cognito.signin.user.admin" here? Or is there a way to return "email" scope using amazon-cognito-identity-js?

2

There are 2 best solutions below

3
On

Change the scope in the console, here:

see image here

2
On
  1. Don't use the "admin" scope, use either "email" or "profile" or even a custom scope. "Email" and "profile" are available out of the box. To add custom scopes - follow the instructions Defining resource servers for your pool.
  2. In Cognito user pool client settings - select the email/profile or your scope. Don't include admin scope unless you need it for a different purpose. All the scopes selected here will be in the issued scopes up in your Cognito user Access Token on login. (Use JWT.MS to examine the token)
  3. In API Gateway, add any of the issues selected scope to the OAuth scope. If the Bearer token has this scope - it will be authorized.