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
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
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'.encode()).decode()
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 '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