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
client_id
andclient_secret
: In Cognito > General Settings > App clients you can find the App client id, then click on Show Details to find the App client secretFor 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
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