TOKEN endpoint returns invalid_client without client secret
Asked Answered
C

7

39

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.

Cupo answered 7/2, 2019 at 16:52 Comment(5)
Any luck on this? I'm having the same problemChymotrypsin
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.Cupo
I finally gave up and created a new Cognito Client App with a secret, and things started working for me as well.Stauffer
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.Ba
@Магнайбаяр Ганзориг annswer is correct and should be an accepted answerCartilaginous
R
48

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.

Ricardoricca answered 14/9, 2020 at 6:10 Comment(1)
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 lotIndraft
E
22

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'
Eury answered 8/7, 2020 at 17:57 Comment(5)
Can you expand a bit on this answer - perhaps some code?Frit
Updated with example.Eury
Yessss ! This is it. Thanks a lotRhineland
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.Seumas
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=<Code>&redirect_uri=<MyRedirect>&code_verifier=<CodeVerifier>&client_id=<MyCognitoClientId>&client_secret=Archlute
S
8

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" }
Smuggle answered 14/8, 2020 at 16:55 Comment(2)
Notice that AWS presented this with Postman: 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 nowKannry
This was my exact issue trying to make a login request through Postman as Postman defaults to using the authorization header. If you change the Client Authentication option from the default (Send as Basic Auth Header) to Send client credentials in body it works.Pushbike
B
3

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".

Baseman answered 20/2, 2023 at 20:27 Comment(1)
That one worked!Fabianfabianism
C
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.

Cichlid answered 10/2, 2019 at 3:16 Comment(1)
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'] = NoneAbsenteeism
S
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.

Selection answered 17/11, 2020 at 8:45 Comment(0)
J
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

Janycejanyte answered 4/11, 2022 at 11:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.