0

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?

tahaerden
  • 121
  • 1
  • 10
  • `const access_token = result.getAccessToken();`try this – Pavindu Apr 01 '22 at 01:07
  • @Pavindu thanks for the answer but it doesn't work. When I use result.getAccessToken() it returns an object containing a jwtToken string and a payload object. – tahaerden Apr 01 '22 at 08:34
  • 1
    `result.getIdToken().getJwtToken()` can u try this one then? – Pavindu Apr 01 '22 at 10:03
  • 1
    @Pavindu it doesn't work also. As I mentioned in Update part in my question, the issue is about the OAuth Scopes. When I add "aws.cognito.signin.user.admin" scope to API method request option it works. Not sure if it is the best practice though. Doesn't seem secure. – tahaerden Apr 01 '22 at 10:13
  • Firstly, authorizer accepts Id Token. Whatever changes you make, test only with the Id token. Next step in your testing should be generating id token and manually testing it on your authorizer in api gateway console. Check if it is passing. – Ninad Gaikwad Apr 02 '22 at 06:42
  • @NinadGaikwad thanks for your answer. As I mentioned, IdToken also doesn't work, the reason being it doesn't have the "scope" object in the payload, so I get "Unauthorized". Secondly, authorizer doesn't only accept IdToken, I currently use AccessToken and it works. For now I just added "aws.cognito.signin.user.admin" scope to the API options. – tahaerden Apr 04 '22 at 07:31

2 Answers2

0

Change the scope in the console, here:

see image here

fedonev
  • 20,327
  • 2
  • 25
  • 34
  • Yep that's what I did as I mentioned in my comment at Apr 1 at 10:13. I'm not sure if it is best practice to allow every user to use "admin" scope though. – tahaerden May 19 '22 at 16:07
  • (@tahaerden: you can hyperlink a specific comment using the one "under its date".) – greybeard Sep 26 '22 at 10:26
  • Thanks @greybeard . In [this comment](https://stackoverflow.com/questions/71698172/aws-api-gateway-authorizer-works-with-cognito-hostedui-but-not-with-access-token/72304923?noredirect=1#comment126723458_71698172) I explained that I used "aws.cognito.signin.user.admin" already. But I don't think it is secure, plus it is a hassle to add it into each API method. – tahaerden Sep 26 '22 at 14:08
-1
  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.
DVM
  • 102
  • 1
  • 3
  • 2
    How do I do that? Let's say I add the custom scope to the API's OAuth Scopes input, can I receive the same scope from inside the access_token? If there is a way to add scopes into access_token response, can I just use "email" instead? Why add a custom one? – tahaerden Sep 22 '22 at 06:01
  • Instead of using the admin scope - you can use "email" or "profile". I've modified my answer for the steps – DVM Oct 01 '22 at 07:26