AWS Cognito; unauthorized_client error when hitting /oauth2/token
Asked Answered
D

11

44

Steps taken so far:

  • Set up new user pool in cognito
  • Generate an app client with no secret; let's call its id user_pool_client_id
  • Under the user pool client settings for user_pool_client_id check the "Cognito User Pool" box, add https://localhost as a callback and sign out url, check "Authorization Code Grant", "Implicit Grant" and everything under "Allowed OAuth Scopes"
  • Create a domain name; let's call it user_pool_domain

Create a new user with a username/password

Now, I can successfully go to:

https://{{user_pool_domain}}.auth.us-east-2.amazoncognito.com/oauth2/authorize?response_type=code&client_id={{user_pool_client_id}}&redirect_uri=https%3A%2F%2Flocalhost

This presents me with a login page and I am able to login as my user which returns me to https://localhost/?code={{code_uuid}}

I then try the following: curl -X POST https://{{user_pool_domain}}.auth.us-east-2.amazoncognito.com/oauth2/token -H 'Content-Type: application/x-www-form-urlencoded' -d 'grant_type=authorization_code&redirect_uri=https%3A%2F%2Flocalhost&code={{code_uuid}}&client_id={{user_pool_client_id}}'

However, this just returns back the following: {"error":"unauthorized_client"}

The token endpoint docs say that unauthorized_client is because "Client is not allowed for code grant flow or for refreshing tokens." which is confusing because I checked the boxes allowing the client to use the code grant flow.

Dipterocarpaceous answered 10/5, 2018 at 2:39 Comment(3)
As Andrew noted, you can get this error when there is a problem with the redirect_uri. Using localhost has never been a problem for me, but I do get this (rather misleading) error message whenever I omit the trailing slash on the redirect_uri when calling the token endpoint. Can you try adding %2F to the end of the redirect_uri?Chatoyant
@MikePatrick WOW thank you so much! It was the missing trailing slash. That's a frustratingly bad error message that I lost a day on but it actually works now!!!Dipterocarpaceous
I found that this also holds if I have a list of redirect uris defined in the app client at the AWS side - when I replaced the list with a single item, and had the client refer to the single item, it worked. Otherwise, I got the redirect_uri error mentioned.Sumerlin
D
66

So, it turns out that the user pool has to have a trailing slash (https://localhost/) and then that trailing slash has to be used in all of the callback URLs. Then it decides to work!

If this does not work, make sure the redirect_uri is exactly the same as defined in the User Pool for "Callback URL(s)"

Dipterocarpaceous answered 10/5, 2018 at 15:48 Comment(7)
You saved my day. The redirect_uri should be exactly the same as we define in Cognito consoleJuneberry
concur to what @Juneberry says. Trailing slash isnt needed but the redirect_uri should be exactly the same as defined in the User Pool for "Callback URL(s)" ex: https://**DOMAINPREFIX**.auth.**REGION**.amazoncognito.com/oauth2/token?grant_type=authorization_code&client_id=**CLIENTID**&code=**AUTHORIZATION_CODE_OBTAINED_FROM_oauth2/authorize_ENDPOINT**&redirect_uri=**CALLBACK_URL_CONFIGURED_IN_USERPOOL**Twelvetone
@Twelvetone lol this was the issue with my configuration. Thanks for pointing it out. I can finally go to sleep...Subtlety
This is so random and not documented in amazon cognito, thank you a lot! This is true for custom domains and urls too: https://example.test/login/Bevon
I love you. After hours of scratching my head, who would have thought the answer was a measly "/".Colbert
I agree that the URLs must match exactly. However I have not found that they must end in a '/'. I am using http://localhost:9090/login just fine.Aristate
@Twelvetone this part about redirect_uri's that need to be EXACTLY the same is missing in the documentation so much! Thanks, I've spent so many hours looking for it...Embay
W
7

I had this error for another reason: I had response_type=token in the request URL, but the implicit OAuth flow was not enabled in the user pool client, so I needed to change it to response_type=code.

Whiny answered 29/4, 2022 at 17:5 Comment(0)
T
4

Everything looks OK to me. I think it may be complaining about the Authorization header missing but not sure. You could try a few things:

1) According to this page (https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html), you shouldn't need to send the Authorization header in the token request, but maybe it is still needed. You could try either passing just the client ID in it (Authorization [client ID]) or configure a secret and try passing Authorization [client ID:client secret] like it says). It usually makes sense to use a client secret for authorization code flow anyway since in this flow, there is a server side component that can securely handle the token exchange.

2) Try using Implicit Flow instead to see if that works. Implicit Flow makes sense for single page apps with no server side component. For that, no client secret is needed.

Tallent answered 10/5, 2018 at 3:2 Comment(4)
I've tried it with the clientID:clientSecret base64 encoded as the Authorization header with no luck. How would I go about using the Implicit Flow? What's the difference?Dipterocarpaceous
I noticed that AWS API Gateway will throw an "unauthorized" error if the redirect URI is not accessible. Now that I think about it, trying to use localhost may be a problem. Think about it ... AWS would need to redirect to that page but it can't because localhost is on your local machine. I would try a non-localhost URL to see if that is causing the problem.Tallent
Here is info about the differences between authorization code flow and implicit flow: #16321955Tallent
If you want to use Implicit Flow, then it is similar to what you just did except the last step is not needed. Instead, you would receive the token from the first request. It is provided in what is known as a URL fragment. The URL fragment can only be read by browsers. This fragment contains the token(s).Tallent
P
4

If you are using amplify and have it configured outside of the CLI and the other answers aren't working for you, one last fix you can try is to ensure you have responseType: 'token' if you are using implicit flow. Fixed things for me.

Auth: {
  oauth: {
    domain : 'your-app.auth.your-region.amazoncognito.com',
    redirectSignIn: environment.cognito.oauthCallbackLogin,
    redirectSignOut: environment.cognito.oauthCallbackLogout,
    responseType: 'token',
    scope : ['email', 'openid', 'profile'],
  }
}
Padova answered 17/2, 2021 at 12:5 Comment(1)
or make sure responseType is code when using Authorization code grantTour
S
3

TL;DR

In addition to all the other answers: Make sure that redirect_uri matches what you sent to /login. Apparently they have to be the same.

Explanation

After applying the existing answers, I was still having trouble:

  • I could successfully get a code from Cognito's /login endpoint
  • But when trying to convert the code to a token using /oauth2/token it fails with unauthorized_client

The part I was doing wrong is outlined in this documentation on the redirect_uri parameter:

redirect_uri Must be the same redirect_uri that was used to get authorization_code in /oauth2/authorize.

Although I got the authorization code from /login and not /oauth2/authorize, this apparently applies to /login as well.

Sheepshead answered 5/7, 2023 at 21:32 Comment(0)
B
1

I agree with @rioastamal and @kiran01bm as well. I did not need a trailing slash and it has to be verbatim as configured for the callbacks.

In my case I had my Redirect URI encoded at definition like this const redirectUri = encodeURIComponent(REDIRECT_URI). Later, when it was used in the POST call to the /token endpoint as part of the params, it resulted as a double-encoded string.

A facepalm moment, but could happen to anyone. Getting rid of one of the encoding fixed it for me.

Bamboo answered 25/8, 2022 at 7:27 Comment(0)
B
1

I configured the UserPoolClient via cloudformation and had the AllowOAuthFlows set to implicit, where to work with amplify/cognito I needed that value to be code.


  GoogleUserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    DependsOn: GoogleUserPoolIdentityProvider

    Properties:
      UserPoolId:!Ref MyUserPool
      AllowedOAuthFlowsUserPoolClient: true
      GenerateSecret: false
      CallbackURLs:  
        - http://localhost:8080
      LogoutURLs:
        - http://localhost:8080
      AllowedOAuthFlows:
        - code
      AllowedOAuthScopes:
        - email
        - openid
      SupportedIdentityProviders:
        - Google
Baikal answered 14/9, 2022 at 3:20 Comment(0)
T
0

Make sure to also include the scope in the request. Like the following

https://domain.auth.eu-central-1.amazoncognito.com/signup?client_id={}&response_type=token&scope=aws.cognito.signin.user.admin+email+openid+phone+profile&redirect_uri=https://www.google.com/
Teraterai answered 4/10, 2021 at 9:50 Comment(0)
S
0

I my case, the issue came from the ACS URL that was incorrect, but so close that I did not see it. It was redirecting my to a page with this error "An error was encountered with the requested page."

Statistics answered 1/9, 2022 at 14:49 Comment(0)
K
0

Authorization code grant means you get a code at the end of that redirect and you have to exchange that code for the respective tokens, and the response Type will be code. And the Implicit grant type is the equivalent of response type token, where in you will get the tokens on the first step itself. So check if you have the correct response type as per your auth flow set in the cognito console.

Kerbstone answered 23/9, 2022 at 5:46 Comment(0)
C
0

In my case, I updated the localhost:port in Allowed callback URLs of cognito app client setting but failed to add localhost:port to Allowed sign-out URLs

Cuttler answered 20/2, 2023 at 10:45 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Hearsh

© 2022 - 2024 — McMap. All rights reserved.