Cognito /oauth2/token endpoint returns invalid_grant error

0

I want to get access token (and set to cookie) from authorization code with Lambda function after sign-in by Hosted UI, but /oauth2/token endpoint returns invalid_grant error.

My Amazon Cognito configuration is following:

  • a Client without secret
  • use Hosted UI to sign-in
  • redirect URI is hosted on a function URL associated to a Lambda function
  • the Lambda function sends a POST request to /oauth2/token however invalid_grant error is returned
    • custom runtime image built with code written in Rust (using cargo-lambda)
    • without Authorization header due to no client secret
    • Content-Type is application/x-www-form-urlencoded
    • body includes grant_type: authorization_code, code: code in query parameters, scope: openid, client_id: my Cognito user pool client id, redirect_uri: the same as specified in the sign-in url

Reproduce steps:

  1. Open the Hosted UI of my Cognito User Pool client
  2. Sign-in a user
  3. Redirected to the authentication page handling my Lambda function, that sends a POST /oauth2/token with code in the query parameters, but returned invalid_grant error

The Lambda function's log with debug log:

START RequestId: 81fd9c22-9dfc-4363-ba5c-6f569baca42c Version: $LATEST
oauth2/token req params: [
(
"grant_type",
"authorization_code",
),
(
"code",
"dd95669d-7ba4-4693-91b7-2e955dd505fc",
),
(
"scope",
"openid",
),
(
"client_id",
"14p0d6vb9am0oi72gj5rpmn5f4",
),
(
"redirect_uri",
"https://btnhtnkhposuph346t5hlchuua0cmojc.lambda-url.ap-northeast-1.on.aws/home/authenticate",
),
]
oauth2/token req: Request {
method: POST,
url: Url {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"maverick-stg.auth.ap-northeast-1.amazoncognito.com",
),
),
port: None,
path: "/oauth2/token",
query: None,
fragment: None,
},
headers: {
"content-type": "application/x-www-form-urlencoded",
},
}
oauth2/token resp headers: {
"date": "Sun, 19 Nov 2023 10:33:13 GMT",
"content-type": "application/json;charset=UTF-8",
"content-security-policy-report-only": "script-src https://d3vhah7crmmd43.cloudfront.net https://maverick-stg.auth.ap-northeast-1.amazoncognito.com; style-src https://d3vhah7crmmd43.cloudfront.net https://maverick-stg.auth.ap-northeast-1.amazoncognito.com; img-src https://d3vhah7crmmd43.cloudfront.net https://maverick-stg.auth.ap-northeast-1.amazoncognito.com; report-uri https://maverick-stg.auth.ap-northeast-1.amazoncognito.com/cspreport",
"set-cookie": "XSRF-TOKEN=11302bca-00b5-44ec-981f-a81162eeaa82; Path=/; Secure; HttpOnly; SameSite=Lax",
"x-amz-cognito-request-id": "4a5f2d91-5480-4f93-b311-243d30f42d45",
"x-content-type-options": "nosniff",
"x-xss-protection": "1; mode=block",
"cache-control": "no-cache, no-store, max-age=0, must-revalidate",
"pragma": "no-cache",
"expires": "0",
"strict-transport-security": "max-age=31536000 ; includeSubDomains",
"x-frame-options": "DENY",
"server": "Server",
}
oauth2/token resp body: 
{
    "error": "invalid_grant"
}

END RequestId: 81fd9c22-9dfc-4363-ba5c-6f569baca42c

I saw the Token_POST event in CloudTrail, that shows 400 response was returned:

{
    "eventVersion": "1.09",
    "userIdentity": {
        "accountId": "428546013367"
    },
    "eventTime": "2023-11-19T10:33:13Z",
    "eventSource": "cognito-idp.amazonaws.com",
    "eventName": "Token_POST",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "13.114.22.190",
    "errorCode": "400",
    "requestParameters": null,
    "responseElements": null,
    "additionalEventData": {
        "responseParameters": {
            "status": 400
        },
        "requestParameters": {
            "code": [
                "HIDDEN_DUE_TO_SECURITY_REASONS"
            ],
            "grant_type": [
                "authorization_code"
            ],
            "scope": [
                "HIDDEN_DUE_TO_SECURITY_REASONS"
            ],
            "redirect_uri": [
                "https://btnhtnkhposuph346t5hlchuua0cmojc.lambda-url.ap-northeast-1.on.aws/home/authenticate"
            ],
            "client_id": [
                "14p0d6vb9am0oi72gj5rpmn5f4"
            ]
        },
        "userPoolDomain": "maverick-stg.auth.ap-northeast-1.amazoncognito.com",
        "userPoolId": "ap-northeast-1_c7AbVaAPa"
    },
    "requestID": "4a5f2d91-5480-4f93-b311-243d30f42d45",
    "eventID": "072fb837-f4e3-42fe-b9c3-c41e820dc5a6",
    "readOnly": false,
    "eventType": "AwsServiceEvent",
    "managementEvent": true,
    "recipientAccountId": "428546013367",
    "serviceEventDetails": {
        "serviceAccountId": "346377544927"
    },
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "maverick-stg.auth.ap-northeast-1.amazoncognito.com"
    }
}

https://ap-northeast-1.console.aws.amazon.com/cloudtrail/home?region=ap-northeast-1#/events/072fb837-f4e3-42fe-b9c3-c41e820dc5a6

What's wrong with me?

jun
asked 6 months ago1013 views
1 Answer
0
Accepted Answer

I've resolved it myself, reading the document carefully again: https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html

App client doesn't have read access to all attributes in the requested scope. For example, your app requests the email scope and your app client can read the email attribute, but not email_verified.

After making email_verified readable, the API now returns the tokens!

jun
answered 6 months ago

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