Getting user information AND aws tokens

0

I want to have my React webapp log a user in using cognito, get access keys, but also get all the attributes of the user from the user pool. I am using the Javascript SDK with the v3 API.

I am trying to follow documentation but all these IDs have me mixed up. What I want to do is to take the 'code' that I get back from the authorizer and get a JWT access/refresh token, AWS access id/secret for services I want to access directly, and some attributes and claims. I want all of that - "this person is named Jovi and here are her keys."

This is what I am attempting. The basic strategy is:

  1. I redirect the user to my cognito hosted login screen
  2. cognito redirects back to my react app with a 'state' and a 'code'.
  3. Use that 'code' to get a Session Token, which is of type Credentials
  4. using a CognitoIdentityClient call GetOpenIdToken to get a JWT
  5. Decode the JWT, it should have first name, last name, e-mail address, and maybe some custom claims I added via a lambda.

My questions are in the code as comments. I think the main problem is I'm not clear how to call GetOpenIdToken(). It wants an IdentityId parameter, but where does that ID come from? Is it an ID for the user pool? How does it know which user I'm asking about?

I guess the last question is do I even need to do this, or when I get redirected back from authorize do I a actually get the the JWT some other way?

I need he AWS access token/key to access services like S3. I really want the other stuff to improve the user experience. I want the JWT so I can make calls to API Gateway using an authorizer.

My react app is being fed to the user by a CloudFront fed by an S3 bucket. I think that means that when I get redirected back from cognito, I can see any cookies cognito set.

I would be possibly open to using Amplify for this if that seems like it would work better for this. I also could write a lambda to deal with all this but I don't think that's necessary. I don't totally understand if the cognito redirect is always a GET or if it could POST something back to me if I wanted (like the user info).

    const [ credentials, setCredentials] = useState<Credentials>();

    if (code) {
        const client = new STSClient({})
        client.send(new GetSessionTokenCommand({
            DurationSeconds: 3600 * 4,
            TokenCode: code /* this is the code that got pushed back in the query string from authorize */
        })).then((response: GetSessionTokenCommandOutput) => {
            /*
              * This is an AWS credentials pair, access id and secret
              * All I need to do is save it and use it to access services like S3
              */
            if(response.Credentials) {
                /*
                  * I am setting credentials in a react state variable but maybe I'm supposed
                  * to just push these to AWS.config.
                  */
                setCredentials(response.Credentials)
            }
        }).then(() => {
            /*
              * This is where I'm most confused.  I got a 'code' back and I want to turn that
              * into JWT access and refresh tokens.  Then I want to be able to use those to
              * access services that require them (for example via API Gateway) and also to
              * be able to pull out attributes and claims.  This will let me have a better user
              * experience, as I can hide UI elements that don't pertain to a user, and show
              * a friendly name on the nav bar
              */
            const client = new CognitoIdentityClient({});

            return client.send(new GetOpenIdTokenCommand({
                IdentityId: 'us-east-1_CX1xxxzzzbbbfG', /* Is this supposed to be the User Pool ID? */
                Logins: {
                    'cognito': code 
                    /* what is the key here really supposed to be?  I'm just using a Cognito built-in user pool. */
                }
            }))
        }).then((response: GetOpenIdTokenCommandOutput) => {
            /* Can I unpack this jwt and get the attributes like name, email, ... */
        })
    }
profile picture
wz2b
asked 2 years ago238 views
1 Answer
1

Hi,

There is two parts to what you are trying to do here and maybe it will help to separate them out. A Cognito User Pool will not give you an STS credential. A Cognito User Pool takes an unauthenticated user, authenticates them via some process and then gives you back a JWT to show they have been authenticated. A Cognito Identity Pool can take a JWT (or SAML token) and exchange that proof of Identity for an STS token.

So in your case, the process needs to be:

There is a great video - https://www.youtube.com/watch?v=tAUmz94O2Qo - that will describe the end to end process.

AWS
Owen
answered a year ago
  • Thanks, Owen.

    I have been using the Amplify library for this so some of what it does was a little hidden to me. It is handling both login and getting an STS credential for me, which is why I wasn't entirely sure what it was doing under the hood.

    After reading through the docs you linked, I now feel like I want to improve things by generating, on the fly, a custom role for each user, then having the Lambdas somehow assume that role. I'm going to have to do some reading to figure out how to do all that.

    Maybe that doesn't make sense. I know I can set up groups that have associated IAM roles. I could set up a per-customer RO and per-customer RW role and still stay within the limits of max IAM roles per account.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions