Closed railsstudent closed 6 years ago
@railsstudent Hi, I think you probably gave incorrect cognito app client id which causes 'invalid_client'.
I just reproduced your steps and get the tokens successfully using Postman. The steps:
create a app client without client secret in Cognito User Pool, and enable Google as an identity provider and enable code grant flow; (If the client was issued a secret, the client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization. The secret is Basic Base64Encode(client_id:client_secret).) It is in our doc: http://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html
Go to the hosted UI (
Go to postman,
make a post request: URL is:
Body: remember to select x-www-form-urlencoded: and put the following,
[{"key":"grant_type","value":"authorization_code"},{"key":"client_id","value":""}]
Then click send request, you will get id_token, access_token and refresh_token.
I got authorization code grant flow working in my angularjs app. When creating client app in user pool, I forgot to uncheck generate client secret checkbox. I create a new client app with no secret key and get the code grant flow working.
Thank you for your help. The above steps should be included the sample app if not in the Amazon documentation.
@railsstudent Glad it works! Thanks a lot for your suggestion, and I will include this part in our sample app doc.
@yuntuowang @railsstudent I am saving facebook user into userpool using auth SDK and able to redirect to it. But I want to see the the current logged in user on the redirect page.Is it possible? If so, which method I have to use?
Answered in another issue: call getCurrentUser() in your onSuccess() callback. @joe455
@yuntuowang Hey, I tried your step by step method from above but I always get the error response: {"error":"invalid_request"} Everything seems to be correct, headers are correct, code is correct and all params are present. Is there anything else I should do?
@jorenvh1, I am not entirely sure why you get "invalid_request". The reason could be wrong clientId or other incorrect parameters. Also, it is important to notice that if the client was issued a secret, the client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization. The secret is Basic Base64Encode(client_id:client_secret). It is in our doc: http://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html
@yuntuowang Thanks for the quick reply!
I am providing the correct clientid because if I change this, this will return a invalid_client error. There's no secret present on the client app.
Is there any way I can debug which parameter is causing the problem? Cause 'invalid_request' isn't really getting me anywhere 🤔
Thanks in advance!
Hi @jorenvh1, can you successfully authenticate successfully with the code grant flow end point and get the code?
Then when you use postman to exchange the code for tokens, then you see this 'invalid_request' error??
@yuntuowang Exactly!
Hi @jorenvh1, can you provide me your parameter settings in Postman when making this Post request?
So mine is: make a post request: URL is: /oauth2/token Header: [{"key":"Content-Type","value":"application/x-www-form-urlencoded"}]
Body: remember to select x-www-form-urlencoded: and put the following, [{"key":"grant_type","value":"authorization_code"},{"key":"client_id","value":""},{"key":"redirect_uri","value":"https://www.amazon.com"},{"key":"code","value":""}] Then click send request, you will get id_token, access_token and refresh_token.
This works, so I suggest you compare your parameters with this. The format should be exactly the same.
@yuntuowang Yes, I am providing those exact parameters, see screenshot below
Hi @jorenvh1, 400 Bad Request means invalid parameter exception.
Your settings here seem correct. Make sure you have set your header correctly.
From the doc we can see: (https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html) Examples of Positive Requests Exchanging an Authorization Code for Tokens Sample Request
POST https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/token& Content-Type='application/x-www-form-urlencoded'& Authorization=Basic aSdxd892iujendek328uedj
grant_type=authorization_code& client_id=djc98u3jiedmi283eu928& code=AUTHORIZATION_CODE& redirect_uri=com.myclientapp://myclient/redirect Sample response
HTTP/1.1 200 OK Content-Type: application/json
{ "access_token":"eyJz9sdfsdfsdfsd", "refresh_token":"dn43ud8uj32nk2je", "id_token":"dmcxd329ujdmkemkd349r", "token_type":"Bearer", "expires_in":3600 }
@yuntuowang I finally figured it out... I was sending the parameter 'redirect_url' instead of 'redirect_uri' Thanks for all your suggestions and time to help me out!
Hi @jorenvh1, awesome!! You are very welcome!
After Successfully login with GOOGLE plus app a user identity is creatin my identity pool after that my own custom ui page is reloading properly see below
when am click continue with google it showing ERROR like this
I have problem with post request authentification while trying to run the code I get error invalide request does anyone know how I could solve this problem, I get this error { error: 'invalid_request' }
const dat = { 'grant_type': 'authorization_code',
'code':code ,
"redirect_uri" : redirect
};
const URLSearchParams = Object.keys(dat).map((key) => { return encodeURIComponent(key) + '=' + encodeURIComponent(dat[key]); }).join('&');
fetch('https://polarremote.com/v2/oauth2/token', {
method: 'POST',
headers: {
'Authorization':Basic ${creds}
,
'Content-Type': 'application/x-www-form-urlencoded',
'Accept':'application/json; charset=utf-8'
}, data: URLSearchParams
}).then(function(res) { return res.json(); }).then(function(body) { console.log(body); });
Hi @balakrishna222111, this is possibly because your scope setting of "Allowed OAuth Scopes" under App client settings of Cognito console is not consistent with the scopes you provides in sample app.
For example, in our sample index.html line 199:
TokenScopesArray :
Hi @tawfikbougerba, you can see the error "invalid_request" cause of many reasons.
Can you double check the detailed steps I posted earlier to make sure the POST parameters are exactly correct? Also, make sure the app client settings on Cognito console page is all consistent, e.g., make sure you have enabled "authorization_code" flow.
@yuntuowang Hi, I have followed the steps above to ensure all my parameters are exactly correct, and my app client does not have a secret, but am still getting 'invalid_request' error.
Is it possible to have http://localhost:4000 as the redirect uri? Or does this have to be https? If it has to be https how is this supposed to be tested in development?
@yuntuowang nvm, the issue was actually that axios was not converting the parameter data from JSON to a query string before sending the request. Changing it to a query string manually fixed the issue
Hi @declan4, glad it worked!!
Hi @yuntuowang
I'm having issue with authorization code flow while trying to marry cognito with spring-security-oauth2
When I exchange code for access token I get 400, "invalid_client" error.
I'm using Cognito User Poll as an identity provider. Manual try with Postman says the same.
My configuration is:
Can I see any logs from Cognito somewhere about what is happening?
Hi @DmytroRybka, you cannot see logs from Cognito. "Invalid_client" error means your client setting has some problems. As I can tell, your callback url is invalid. We don't support HTTP protocol, so you need to use HTTPS. And we also don't recommend your callback url containing "localhost".
You also need to set "sign out URLs" correctly.
For scopes, make sure your setting on console is exactly same as in your code configuration.
Thanks.
Hi @yuntuowang , Thanks for the idea with https but unfortunately still getting the same error. I changed to use self signed certificate. The issue is that "implicit flow" works for me just fine. The only issue is when I use authorization code and try to exchange code for access token. Theoretically should not be a difference between both flow handling. Do you think I Self signed might be an issue?
Hi @DmytroRybka, I don't think Self signed is an issue.
When you use authorization code grant flow, can you successfully get code parameter in the callback url? And then you see "invalid_client" error when SDK try to use this code to exchange for tokens? If yes, can you reproduce this error and tell me which region are you using our service, the timestamp(which minute), your user pool id and your client id. Then I can pull the log for you to see what happened. Thanks!
curl -X POST -H "Authorization: Basic c2E***XE1a2tqZ2M=" -H "Content-Type: application/x-www-form-urlencoded" -d '{ "grant_type":"authorization_code", "redirect_uri":"https://www.google.com", "code":"801c738e-f7c6-4bc3-8409e4", "client_id":"sa0adikbpbdebakl79" }' https://mycompany.auth.us-east-2.amazoncognito.com/oauth2/token
Can anybody tell what's wrong with the above command? I'm getting {"error":"invalid_request"}.
Hi @sunsoori, "invalid_request" usually means the parameters you put in the command is inconsistent with the app client settings you have on cognito console. Can you double check those are correct?
hi @yuntuowang Thanks for the response. apparently I have to do like this: -H "Content-Type: 'application/x-www-form-urlencoded'" and single quote within double quote.
But now, I'm getting 405 Method not allowed. Any thoughts?
Here's the verbose log of the curl command
< HTTP/2 405 < date: Fri, 16 Mar 2018 18:29:20 GMT < content-length: 0 < set-cookie: XSRF-TOKEN=0d8cde7f-27c0-41d1-ab95-6535c4f1a997; Path=/; Secure; HttpOnly < x-amz-request-id: fd1eeb13-230a-4e8b-bb4b-79debb79f662 < x-application-context: application:prod:8443 < 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 < allow: GET
funny enough, I'm getting 405 (Method not allowed) for this one
curl -v -X POST https://mycompany.auth.us-east-2.amazoncognito.com/oauth2/token
I am not sure about this 405 error. But your command seems missing parameters.
Sample Request:
POST https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/token& Content-Type='application/x-www-form-urlencoded'& Authorization=Basic aSdxd892iujendek328uedj
grant_type=authorization_code& client_id=djc98u3jiedmi283eu928& code=AUTHORIZATION_CODE& redirect_uri=com.myclientapp://myclient/redirect
Details:
https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html
Sorry for being so stupid @yuntuowang , but where do I take my client_id
? Or where do I create my app client?
I have created a project on Mobile Hub, but I do not know what is this client_id
. Do I get it from the aws_config.js
file?
Moreover, where do I get the hosted UI URL
of the app? (for seek of clarity, I am trying to use the authorization grant flow to access aws from a native Ionic app. Using this SDK I cannot get a refreshToken from the authorization flow, so I have to implement the grant flow)
Hi @SimoneMSR, you need to go to Cognito console to create a user pool and create an app client there. At the client settings tab, you can set all the fields. The hosted UI URL will be constructed from the app client settings. It looks like: https://****.auth.us-east-1.amazoncognito.com/oauth2/authorize?response_type=token&client_id=*******&redirect_uri=https://www.amazon.com
If you use the authorization code grant flow, you will get refreshToken using this SDK.
Please refer to following doc: https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-ux.html
You can find more resources too on Cognito doc.
Why is cognito NOT having "Resource Owner Password Credentials Grant" flow? It only has Authcode grant, implicit and client credentials flows.
Hi @sunsoori, I will make this as a feature request on behalf of you. Thanks!
Thankyou so much. Would you mind telling how long it usually takes, for a feature to be released after making the request?
Hi @sunsoori, at this point, it is hard to comment on the timeline. But we will take this feature request in our queue for sure. Thanks!
Thank you for the reply @yuntuowang. It was just effective!
But now facebook tells me that the URL is not included in the domains. I used https://CLIENT-APP-DOMAIN.auth.eu-west-1.amazoncognito.com
. Where am I wrong?
I cannot use https://CLIENT-APP-DOMAIN.auth.eu-west-1.amazoncognito.com/oauth2
as domain in Facebook...
There is a field called "redirect url" in Facebook setting, you need to put something like this: https://your-domain-prefix.auth.eu-west-1.amazoncognito.com/oauth2/idpresponse
Done!
By the way I had to add a mapping on the cognito pool, a mapping from the email
facebook attribute so the email
in the user pool, otherwise in the callback url I would have got an error!
Thank you @yuntuowang , this is pretty nice that you are here, let me feel not alone!
I'm unable to get a token from cognito oauth2/token endpoint after getting the authorization code successfully. I'm using an app client with a client secret.
request:
curl -X POST \
https://domain.auth.us-east-1.amazoncognito.com/oauth2/token \
-H 'Authorization: Basic xxxxxxxxx(base64 of clientId:clientSecret)' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&client_id=xxxxxxxx&code=xxxxx-
xxxx-4xxaf7-xx-d5497d5e000e&redirect_uri=https://www.example.com'
response:
HTTP 500
{
"error": "Internal Error"
}
Furthermore I'm using authorization code grant
and implicit grant
for the allowed oauth flows
and I was able to get the token when using the implicit grant.
my auth request:
https://domain.auth.us-east-1.amazoncognito.com/oauth2/authorize?response_type=code&client_id=xxxxxxxxxx&redirect_uri=https://www.example.com.&state=STATE&scope=openid+phone+email+profile+aws.cognito.signin.user.admin
Please let me know if I'm doing anything stupid here.
Hi @YasithLokuge, can you double check your scope setting under your app client setting? They must be consistent as "openid+phone+email+profile+aws.cognito.signin.user.admin".
If they are consistent, and token endpoint still doesn't work for you, can you send me an email about your UserpoolId, clientId, AWS account Id and the timestamp which you had this error(better to minute)? My email address is wyuntuo@amazon.com
Thanks a lot!
Hi @yuntuowang, Requested details have been sent via email. Thanks!
Through the email discussion with @YasithLokuge, implicit grant flow and authorization code grant flow works for him. Also, /oauth2/token endpoint works for him too.
Hi @yuntuowang: Sorry to perform thread necro but I'm having similar problems that I can't seem to resolve.
I am getting an invalid client id error trading authorization code for token even though I can't find anything wrong.
I have triple checked that the client id I am using is the one on my App Client Settings page (I only have one) and all identity providers are enabled (in my case, cognito identity pool and facebook). I have both Authorization Code Grant and Implicit Grant both enabled as well as all scopes enabled.
I have a client secret, have triple checked that value is correct, and I am using it and the client id to form the "Authentication: Basic (base64 encoded value of clientid:clientsecret) and adding this header, in addition to the Content-Type x-www-form-urlencoded.
My code to create the base64 hash: client_id=settings.COGNITO_CLIENT_APP_ID secret = settings.COGNITO_CLIENT_SECRET secret_token = client_id + ":" + secret encode_string = base64.b64encode(secret_token.encode()) hash = base64.b64encode(encode_string).decode("utf-8")
This is what the request looks like in postman:
Please advise, I do not see any reason this should not work.
@yuntuowang My access token doesn't work in API gateway but my Id token works. Any reason? I've attached a cognito user pool as an authorizer to one of the API in the API gateway.
is there a way to set the expiration time for access toekns in cognito? I want to set it to NEVER EXPIRE
Hi @sunsoori , no way to set access token and id token to other expiration time. Their valid time is one hour. However, you can set the expiration time for refresh token when you create an app client on Cognito user pool console/CLI.
Please refer here:
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html
First off -> Super Special Thanks to Crystal (@yuntuowang) for her awesome contributions to this thread!
Now for the journey and headaches we experienced and lessons learned in the first steps of implementing this our Serverless Web Application that will use S3 static pages, Cognito Login UI and Application Gateway with Lambda Functions to talk to S3 and RDS.
We are in the beginning stages of this so please excuse any obvious errors and politely correct them as we are still learning also. One HUGE frustration was that the Amazon Engineers seem to be blessing Angular, React and Vue in their examples (especially with Amplify docs - which we were tempted to use because some older AWS libraries are on the way out) without considering more conventional approaches like jQuery (which we use extensively). So finding actual examples of how to do this has been a PAIN!
Small RANT: We often feel that Amazon functionality is presented like a minimum of five (5) HUGE boxes of Legos form different kits without any final instructions of what they will make. As we route around the box of functionality, we see a lot of really cool pieces, but no real picture of how to connect them together to get to the final goals you have. The result has been a LOT of Dead Ends, or very late discovery that other functionality that is easier to use (like Cognito UI) but also somewhat of a pain to understand the requirements for it. I hope someone from Amazon sees this and takes initiative to improve it across all their documentation. (AWS docs often reads like meeting notes for a meeting we were never invited to and the people who wrote it understand completely).
That all being said - I wanted to share what we have learned after quite a few hours of testing with limited success in the hopes that it helps others trying to implement non-Angular/React/Vue/bla/bla/bla approaches.
---- The LOGIN URL ----
https://>>yourDomain<<.auth.us-east-1.amazoncognito.com/login?response_type=code&client_id=>>yourClientId<<&redirect_uri=>>yourRedirectURLEndpoint<<
yourDomain = obviously your your application root domain name
yourClientId = your specific App Client Id that was created when you defined the App Client -- NOTE: Web Apps do NOT require a App Client Secret ID, and they are NOT created by default.
response_type = code -- NOTE: This can be either "code" or "id_token" - the "id_token" produces the one (1) hour limited token directly, the id_token does NOT include a refresh_token! If you want to obtain the refresh_token, you must request the "code" response_type to use it later. (keep reading)
redirect_uri = Callback URL in your App Client Settings -- NOTE: Notice the "i" not "redirect_url" - this is MUST be the EXACT SAME as the Callback URL in your App Client Settings - it MUST ALSO be an HTTPS endpoint!
As a side note: on the App Client Settings - we flagged Authorization Code Grant and Implicit Grant as well as openid (we did not fully debug - but these seem to follow the advice of others).
Once you have the LOGIN URL properly configured - you will get a Login Screen from Cognito when you go to it in your Browser. It works as expected. If you get an error on the login screen (or a completely blank screen), it is likely a problem with the format of your LOGIN URL and/or your settings. Recheck everything -- especially the redirect_uri as it is often overlooked for both the variable name and correct and value.
---- Using the "code" Response to get a Refresh Token ---- Since our application has a goal of being used LONGER than one (1) hour for users, the id_token is not useful in this scenario. To get around this we discovered we needed the "code" instead and then use that to obtain the refreh_token by making a call to the following URL:
` https://>>yourDomain<<.auth.us-east-1.amazoncognito.com/oauth2/token
BUT the "code" that comes back has a few "quirks" you need to be aware of.
1) I read somewhere that the "code" returned is only valid for five (5) minutes. This may or may not be the case - Amazon can better confirm this. If this is the case, it would explain a lot of problems we were possibly having while trying to debug other areas of this transaction - when the darn thing was expired and not going to work anyway. (sigh).
2) The "code" can apparently ONLY BE USED ONCE (1x) to request the oatuh/token endpoint! We have confirmed this repeatedly using both live testing and stand alone testing via Postman (a cool app if you have not tried it - it saved our bacon on figuring this out!).
---- THE AJAX REQUEST via jQuery ---- Again, I know Angular/React/Vue are apparently what the hip kids are using these days, but we prefer the old-reliable jQuery for most of our apps (and I think a bunch of you still do also).
Assuming you have jQuery loaded properly - the AJAX request is pretty simple:
Helper Function for extracting "code" from the Resulting URL function getQueryVariable(variable) { var query = window.location.search.substring(1); var vars = query.split('&'); for (var i = 0; i < vars.length; i++) { var pair = vars[i].split('='); if (decodeURIComponent(pair[0]) == variable) { return decodeURIComponent(pair[1]); } } console.log('Query variable %s not found', variable); }
Extract the 'code' using the helper function, set to 'cognito_code' variable cognito_code = getQueryVariable('code');
AJAX Body Parameters var bodyParams = { grant_type: 'authorization_code', client_id : '>>yourClientId<<', redirect_uri : '>>yourRedirectURLEndpoint<<', code : cognito_code };
AJAX Request $.ajax({ url: 'https://>>yourDomain<<.auth.us-east-1.amazoncognito.com/oauth2/token', dataType: 'json', type: 'POST', data: bodyParams, success: function (dataObj) { console.log('SUCCESSFUL REFRESH REQUEST!'); console.log(JSON.stringify(dataObj)); }, error: function (request, status, err) { console.log("got to the error!" + JSON.stringify(status) + ' --> '+JSON.stringify(err)); } });
NOTE: dataType = 'json' -- IF you put in 'application/json' you will not get a 'success' event - it will result in a 'parseError' and defer to statusCode for the handling. (found this out the hard way). So to our surprise a simple 'json' dataType was all that was required to properly handle the 'success' event.
ALSO - you will read in the docs that "Headers" are required. Specifically "Authorization" = "Basic
We FOUND THAT THIS WAS NOT NECESSARY OR REQUIRED for applications that DO NOT have a secret_id defined for the App Client! (this was a significant point of confusion and testing to figure out).
The ONLY THING that was required was the BODY of the AJAX Request to be setup properly with the request variables and values as per the example above.
THE RESULT of the above call will produce an Object - should look like the following:
{ "id_token":".....", "access_token":".....", "refresh_token":".....", "expires_in":3600, "token_type": "Bearer" }
I hope that this post was well received and useful to anyone trying to also figure this out. We have more to do with this, but this is a milestone that we achieved to get this "basic" thing talking with Cognito... Now on to the next steps and more testing....
Hi,
My code execution goes like below,
var auth = new AWSCognito.CognitoIdentityServiceProvider.CognitoAuth(authData); var curUrl = window.location.href; auth .parseCognitoWebResponse(curUrl); auth .getSession();
I am able to see the login screen, once I enter username and password and click the sign in button, the control goes to auth.userhandler onFailure method.
what might be the problem? How can I check?
Could you please help?
Thank you!
Can amazaon provide an sample of Authorization code grant flow?
I tried to use google to login Cognito User Pool but token endpoint returns 'invalid_client' When I returned client id and client secret of google in header and encrypted with base64, the endpoint returned "internal error" error message.
I am stumped here. Thanks