35

I am having difficulty with the authorization code flow in Amazon Cognito. The workflow that I am trying to build is the following:

  1. A user authenticates with the built-in Cognito UI.
  2. Cognito redirects back with the authorization code.
  3. I send the code to server where it's exchanged for tokens using /oauth2/token endpoint.

I have created a client without client secret. I authenticate using the Cognito UI, get back the code, then send the following with Postman:

URL: https://MY-DOMAIN/oauth2/token
Method: POST
Headers: 
Content-Type: application/x-www-form-urlencoded
Body:
  grant_type=authorization_code&
  client_id=<my-client-id>&
  code=<code-from-cognito-ui>&
  redirect_uri=<my-redirect-url>

I do not use Authorization since there's no client secret.

In return I receive:

Code: 400
Body: { "error": "invalid_client" }

The app client is allowed authorization code grant in the AWS Cognito console.

Anton Baranenko
  • 564
  • 1
  • 4
  • 7
  • Any luck on this? I'm having the same problem – Brendan Samek Jun 03 '19 at 00:53
  • I repeated the same steps after some while and they worked. I do not know/remember exactly why, probably missed something initially. But if you attach the screenshot from your postman/another utility that you are using, I can check what might be wrong. – Anton Baranenko Jun 05 '19 at 18:47
  • I finally gave up and created a new Cognito Client App with a secret, and things started working for me as well. – jerhewet Feb 04 '20 at 15:49
  • 1
    I also faced that kind of issue. The problem was creating client with client_secret. You should create your client by "Generate client secret" option unchecked. Because Authorization code flow works client side that means your client must be created with public typed. That works perfectly. – Магнайбаяр Ганзориг Jan 22 '21 at 09:41
  • 1
    @Магнайбаяр Ганзориг annswer is correct and should be an accepted answer – cherish sham Feb 23 '22 at 08:30

7 Answers7

45

Does not seem to be mentioned anywhere in the docs though, If you have created the client app with client_secret you should add the client_secret to the params for it to work.

curl -X POST \
'https://<Cognito User Pool Domain>/oauth2/token?
grant_type=authorization_code&
code=8a24d2df-07b9-41e1-bb5c-c269e87838df&
redirect_uri=http://localhost&
client_secret=xcxxxs2r234XXXXXX&
client_id=55pb79dl8gm0i1ho9hdrXXXXXX' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Content-Type: application/x-www-form-urlencoded'

Or you need to create the app with "generate client_secret" = false. Also By default, user pools generates a client secret for your app.

YasirAzgar
  • 1,385
  • 16
  • 15
  • This worked for me! I had an app with client secret but i was not passing it so it was giving me error! Thanks a lot – alext Oct 06 '22 at 22:50
17

The problem is with Authorization header.

When using client without client secret Authorization header is not required.

Example:

curl -X POST \
'https://<Cognito User Pool Domain>/oauth2/token?
grant_type=authorization_code&
code=8a24d2df-07b9-41e1-bb5c-c269e87838df&
redirect_uri=http://localhost&
client_id=55pb79dl8gm0i1ho9hdrXXXXXX&scope=openid+email' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Content-Type: application/x-www-form-urlencoded'
Ashish Kumar
  • 189
  • 1
  • 4
  • Can you expand a bit on this answer - perhaps some code? – stdunbar Jul 08 '20 at 18:50
  • Updated with example. – Ashish Kumar Jul 08 '20 at 19:55
  • 1
    Yessss ! This is it. Thanks a lot – Bodom Vu Jul 09 '20 at 07:54
  • agree with @h-kippo. While what is posted as the answer is not wrong but this is not the right answer. his answer below is the right one. – Anupam Gupta Mar 01 '21 at 15:52
  • 4
    Thanks this information was missing in my postman configuration to retrieve the access token. In postman there is an dropdown option "Client Authentication" with "Send as Basic Auth header" or "Send client credentials in body". When it was added to the header I got "invalid_client" too. But I don't have client credentials with my OAuth2 flow. Request body `grant_type=authorization_code&code=&redirect_uri=&code_verifier=&client_id=&client_secret=` – EinApfelBaum Jul 15 '21 at 10:34
7

I would comment on the other solutions, but not enough rep yet.

As some additional information to anyone who comes across this issue in the future:

Not only is the Authorization header not required... it's Not Allowed.

Saying "Not Required" led me to believe it was optional. In fact, if you pass that along the request, I found that the response would often be as described by OP:

Code: 400
Body: { "error": "invalid_client" }
Ruben Helsloot
  • 12,582
  • 6
  • 26
  • 49
Taylor Buckner
  • 133
  • 1
  • 3
  • Notice that AWS presented this with Postman: https://www.youtube.com/watch?v=WgvVxKf2CFc I tried it without the Client Secret, and I had the same HTTP 400 mentioned in this Post. So, there are two possibilities: 1. Postman was not sending the Authorization header when they recorded that video 2. The service did not care about it back then, but it does now – Gabriel C Mar 20 '22 at 05:48
1

I had a similar issue when working with Cognito on iOS (not amplify) but I figured it out that I needed to actually send nil (for swift).

I'm not sure if that will help your situation but here's what I have in Swift:

@objc func config(_ call: CAPPluginCall) {
    let appClientId = "myclientid";
    let scopes = Set<String>(["openid", "email"]);
    let signInRedirectUri = "com.myappurl://signin";
    let signOutRedirectUri = "com.myappurl://signout";
    let webDomain = "https://[myappdomain].auth.us-east-2.amazoncognito.com";

    // NOTICE my nil here for appClientSecret, if I used "" it would throw the error you are seeing
    let config = AWSCognitoAuthConfiguration(appClientId: appClientId, appClientSecret: nil, scopes: scopes, signInRedirectUri: signInRedirectUri, signOutRedirectUri: signOutRedirectUri, webDomain: webDomain);

    AWSCognitoAuth.registerCognitoAuth(with: config, forKey: "AWSCognito")
    call.resolve()
}

It may not answer the situation you have exactly but this is what worked for me to remove the horrible error invalid_client.

Chris
  • 1,418
  • 2
  • 16
  • 34
  • I was using Python and Flask-AWSCognito, and I had to set the env var `AWS_COGNITO_USER_POOL_CLIENT_SECRET` to `None`: ```app.config['AWS_COGNITO_USER_POOL_CLIENT_SECRET'] = None``` – A. Saunders Mar 11 '23 at 07:00
1

In the comments of the question you mention:

repeated the same steps after some while and they worked.

I stumbled upon the same or similar problem. The solution for me was not to use a previously signed-in session. I had to sign out or open an incognito/private browser session and sign in again to resolve the issue.

All the parameters in the question are valid according to the documentation.

h-kippo
  • 429
  • 1
  • 5
  • 10
1

I was having a similar issue that was resolved by setting Client Authentication from the default "send as basic Auth header" to "Send client credentials in body".

D Malan
  • 10,272
  • 3
  • 25
  • 50
0

I had same situation: Code: 400 Body: { "error": "invalid_client" } Like other friends mentioned, App client created with client_secret need client_secret in API call then it works

RishiH
  • 1