Skip to content
Advertisement

How to use the code returned from Cognito to get AWS credentials?

Right now, I’m struggling to understand AWS Cognito so maybe someone could help me out. I set a domain to serve Cognito’s hosted UI for my User Pool like what’s described here. So when I go to https://<my-domain>.auth.us-east-1.amazoncognito.com/login?response_type=code&client_id=<MY_POOL_CLIENT_ID>&redirect_uri=https://localhost:8080 I get a login page where my users can login to my app with Google. That part is working great.

I’m confused about what to do with the code that is returned from that page once my user logs in. So once I get redirected to Google and authorize the application to view my information, I get redirected back to one of my URLs with a code in the query params. Right now I’m redirecting to localhost, so the redirect URL look like this:

https://localhost:8080/?code=XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX

What exactly is this code? Also, how do I use it to get access to AWS resources for my user?

Advertisement

Answer

First off, screw authentication a thousand times. No one deserves to spend half a day looking at this shit.

Authentication for API Gateway Authorized with Cognito

Ingredients

  1. client_id and client_secret: In Cognito > General Settings > App clients you can find the App client id, then click on Show Details to find the App client secret

  2. For the header Authorization: Basic YWJjZGVmZzpvMWZjb28zc... you need to encode those two with: Base64Encode(client_id:client_secret), for example in Python:

    import base64  
    base64.b64encode('qcbstohg3o:alksjdlkjdasdksd')`  
    

    side note: Postman also has an option to generate this in Authorization > Basic Auth

  3. redirect_uri: passed in the body, it is the callback url that you configured in App integration > App client settings.
    This MUST match with what you configured or you will get a totally unhelpful message { "error": "invalid_grant" }

Example of a request to get a token from the code:

curl --location --request POST 'https://mycognitodomain.auth.us-east-1.amazoncognito.com/oauth2/token' 
--header 'Content-Type: application/x-www-form-urlencoded' 
--header 'Authorization: Basic <base64 encoded client_id:client_secret>' 
--data-urlencode 'grant_type=authorization_code' 
--data-urlencode 'client_id=<client_id>' 
--data-urlencode 'code=<use the code you received post login>' 
--data-urlencode 'redirect_uri=https://myapp.com'

This will return your tokens:

{
  "access_token":"eyJz9sdfsdfsdfsd", 
  "refresh_token":"dn43ud8uj32nk2je",
  "id_token":"dmcxd329ujdmkemkd349r",
  "token_type":"Bearer", 
  "expires_in":3600
}

Then take the id_token and plug into your API call:

curl --location --request GET 'https://myapigateway.execute-api.us-east-1.amazonaws.com/' 
--header 'Authorization: <id_token>'

Ok, this is tagged as JavaScript but since we also suffer in Python

Friendly reminder: this is an example, please don’t hardcode your secrets.

import requests

# In: General Settings > App clients > Show details
client_id = "ksjahdskaLAJS ..."
client_secret = "dssaKJHSAKJHDSsjdhksjHSKJDskdjhsa..."

# URL in your application that receives the code post-authentication
# (Cognito lets you use localhost for testing purposes)
callback_uri = "http://localhost:8001/accounts/amazon-cognito/login/callback/"

# Find this in: App Integration > Domain
cognito_app_url = "https://my-application-name.auth.us-west-2.amazoncognito.com"

# this is the response code you received - you can get a code to test by going to
# going to App Integration > App client settings > Lunch Hosted UI
# and doing the login steps, even if it redirects you to an invalid URL after login
# you can see the code in the querystring, for example:
# http://localhost:8001/accounts/amazon-cognito/login/callback/?code=b2ca649e-b34a-44a7-be1a-121882e27fe6
code="b2ca649e-b34a-44a7-be1a-121882e27fe6"

token_url = f"{cognito_app_url}/oauth2/token"
auth = requests.auth.HTTPBasicAuth(client_id, client_secret)

params = {
    "grant_type": "authorization_code",
    "client_id": client_id,
    "code": code,
    "redirect_uri": callback_uri
}

response = requests.post(token_url, auth=auth, data=params)

print(response.json()) # don't judge me, this is an example
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement