I have a userpool in cognito which uses Google as the identity provider.
Now, using Amplify, we do a FederatedSign with provider as 'Google' as shown below.
Auth.federatedSignIn({ provider: "Google" });.
This gives me back the access token, id token. But the refresh token is empty.
This is for the oauth responseType:'token' configuration.
I have seen elsewhere that we need to change the grant type to 'code' i.e responseType: 'code' in order to get the refresh token.
But in this scenario, I am getting 'code = some-value' in the callback url and not the access token and refresh token.
What am I missing here?
My aim is to be able to get the refresh token - and using this Amplify would refresh the session once the access token in invalid.
You need to change oauth.responseType in your config to 'code' instead of 'token'. I'm getting an error when I do that and I'm not sure why, but this is what I found you need to do.
I am using parseCognitoWebResponse and had the same problem.
Within your User Pool go to App Clients. Check your Cognito App Client and make sure no client secret is generated. If it is filled in recreate an App Client without generating a Client Secret
Change the response_type to code
window.location.href = `https://${yourCognitoDomain}?response_type=code&client_id=${yourClientId}&redirect_uri=${cognitoRedirectUrl}`
Related
I created "test-App" application in API Manager WSO2 with the grant types of "refresh-token" "SAML2", "PASSWORD" "Client Credentials" and "JWT"
I also Created a "test"
To use the webservices behind API manager, First, I should call https://localhost:9443/oauth2/token) to get a access-token
Unfortunately, if I call the link again, instead of receiving the same access-token, the system will generate a new access-token and the previous access-token would be expired. ( I think this link is more like refresh token rather than get the access token).
So, How can I Separate getting available access-token and Refresh-token link in WSO2 API Manager ?
In the latest versions of API Manager you have JWT tokens. When you request a new token it always generates a new token. But it doesn’t revoke the previous access token.
In the earlier versions of APIM, opaque tokens were supported and it has a different behavior. When you request a token, if it is not expired you get the same token.
Please read more about refresh grant here https://apim.docs.wso2.com/en/latest/design/api-security/oauth2/grant-types/refresh-token-grant/
If you have not done any other configuration changes, invoking https://localhost:9443/oauth2/token URL will always generate a new JWT token without expiring the earlier one. However, the token validity can be changed in the Dev Portal while generating the access token.
I'm using django-oauth-toolkit with djangorestframework where our partner user will register their application and get application credentials (client id and client secret) which then used to get access token that can be used further to get our server resources. Upto now I'm able to convert those form based application registration process and other apis through rest. But while I hit for access_token only access token with expire are coming as response. Refresh token also supposed to come along the access token but it's not. What I'm missing here...
Below is the sample api response for access_token
And the oauth2 settings
FYI: I'm using Client type as "Confidential" and Authorization grant type as "Client Credentials"
Findings: This may be helpful for others
There is no need for refresh token for grant type client credentials.
Further descriptions RFC doc ; grant type client credentials
I am trying to get ID token and Refresh token along with access token from Azure AD app via Postman by using below parameters:
GET
https://login.microsoftonline.com/mytenant_id/oauth2/v2.0/token
client_id='myclient_id'
&client_secret='myclient_secret'
&grant_type=authorization_code
&scope=https://graph.microsoft.com/.default
&redirect_uri=https://jwt.ms
I am able to get the access token, but not sure why I am not getting ID token and Refresh token along with it.
Atfirst, I tried with client_credentials flow, but I came to know I have to use auth code flow or OpenID Connect in order to get those tokens.
So I shifted to auth code flow. But still I'm getting access token only:(
I have also enabled the below options in the Portal
What else settings are needed to get the tokens? Any suggestions would be appreciated.
Edited:
I have given below API permissions:
Please note that, getting ID token and Refresh token along with access token depends on the scope/API permissions you grant to the application as mentioned in this MsDoc.
I tried to reproduce the same in my environment and added scopes like below:
After adding the openid and offline_access in the scope, I got all tokens successfully like below:
I am developing an application that uses AWS Cognito as the Identity Provider. So the user authenticate on AWS Cognito Pool and get the Access Token, Access ID and Refresh token.
Then the user can make backend requests to my app. I get the Access Token validate it, get the user profile on Cognito AWS and authorize the request.
The problem is that after the Access token has expired, and the client send the expired token to the backend, the backend app get an error (token experied or not authorized).
How can I make this workflow works?
I was thinking in send to the client a message that the token has expired, and the the cliente refresh it against the Cognito Pool. Is it the correct approach?
When you get the Access Token, ID and Refresh token from Cognito User Pools, you must cache it locally. The Access and the ID token are valid for 1 hour and should be reused as much as possible within that time period.
These tokens are JWT tokens and hold the expiry time within themselves. You can decode the JWT token and also cache this expiry along with the token. Every time the cache for the tokens is accessed, also check the current time against the cached expiry time. If expired, use the Refresh token to obtain the latest Access and ID token and cache the tokens and expiry again.
If you use one of our high level SDKs for Android, iOS or JavaScript, the SDK manages all of this for you.
you can find more information How-to use them on this link.http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html.
To use the refresh token to get new tokens, use
the AdminInitiateAuth API, passing REFRESH_TOKEN_AUTH for
theAuthFlow parameter and the refresh token for
the AuthParametersparameter with key "REFRESH_TOKEN". This initiates
the token refresh process with the Amazon Cognito server and returns
new ID and access tokens.
In short, call the AdminInitiateAuth action with the refresh token. Take a look at the SDK of your development language you prefer.
In my projects I use AWS Amplify library and I found this approach to work:
Configuration:
import Amplify, { Auth } from "aws-amplify";
Amplify.configure({
Auth: {
userPoolId: <USER_POOL_ID>,
userPoolWebClientId: <USER_POOL_WEB_CLIENT_ID>
}
});
Refresh tokens
try {
const currentUser = await Auth.currentAuthenticatedUser();
const currentSession = currentUser.signInUserSession;
currentUser.refreshSession(currentSession.refreshToken, (err, session) => {
// do something with the new session
});
} catch (e) {
// whatever
}
};
More discussion here: https://github.com/aws-amplify/amplify-js/issues/2560.
I am able to successfully retrieve an identity token for my Custom Authentication Provider (Developer Authentication). This is implemented using the Cognito devauth demo servlet.
This token is returned to a browser running AWS JS SDK. When I make a call to getCredentialsForIdentiy, I receive the 'Invalid Login Token' error.
POST https://cognito-identity.us-west-2.amazonaws.com/ 400 (Bad Request)
app.js:150 Error: Invalid login token. Not a Cognito token.
at constructor.a (aws-sdk-2.58.0.min.js:41)
at constructor.callListeners (aws-sdk-2.58.0.min.js:41)
at constructor.emit (aws-sdk-2.58.0.min.js:41)
at constructor.emitEvent (aws-sdk-2.58.0.min.js:41)
at constructor.e (aws-sdk-2.58.0.min.js:41)
at i.runTo (aws-sdk-2.58.0.min.js:43)
at aws-sdk-2.58.0.min.js:43
at constructor.<anonymous> (aws-sdk-2.58.0.min.js:41)
at constructor.<anonymous> (aws-sdk-2.58.0.min.js:41)
at constructor.callListeners (aws-sdk-2.58.0.min.js:41) "NotAuthorizedException: Invalid login token. Not a Cognito token.
at constructor.a (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:615)
at constructor.callListeners (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:30513)
at constructor.emit (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:30224)
at constructor.emitEvent (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:16590)
at constructor.e (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:12285)
at i.runTo (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:43:7277)
at https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:43:7482
at constructor.<anonymous> (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:12495)
at constructor.<anonymous> (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:16645)
at constructor.callListeners (https://sdk.amazonaws.com/js/aws-sdk-2.58.0.min.js:41:30619)"
I am passing to getCredentialsForIdentity the following params.
identityId: <returned from servlet in region:guid format>
customRoleArn: <that maps to authenticated role>
Logins: <cognito-identity.amazonaws.com = token returned by congito>
I notice that new congnito identity was created by using id browser. So, the token interaction with the servlet seems correct. But the token is being rejected.
What am I missing here? How can I troubleshoot it further?
Edit:
Browser client: javascript sdk, version 2.58.
Essentially writing a JS client to this demo . The modifications is only to get token as part of login call itself. The generated token corresponds to a role that only has IOT client access. (I wonder if that policy needs to expand). Eventually the users will be validated against an internal ID store instead of this demo.
Edit 2:
Instead of calling getCredentialsForIdentiy against Cognito Service, I invoked assumeRoleWithWebIdentity against STS and that worked. The use of Basic Flow instead of Enhanced flow here. . Really not sure why enhanced flow did not work but will take the basic flow approach for now.
So, the AWS documentation here is either inaccurate or documents an inefficient scenario.
Using JavaScript Cognito API, my Developer Provider returned token could not be used with GetCredentialsForIdentity against Cognito API. (this is what prompted me to ask this question).
However, I can use the same token against STS API and invoke AssumeRoleWithWebIdentity which essentially returns the same response parameters as GetCredentialsForIdentity above. This is the approach I took.
Basic Auth Flow documentation in the first link seems inaccurate. Because it lists 'get credentials' and 'assume role' as required steps but only one is actually needed. Also, from a browser, this is an API call out to an Amazon service. So using Enhanced Flow instead of Basic does not seem like an advantage if it worked.
I had this same problem, using V3 of the Javascript SDK, and struggled for a very long time! The currently accepted answer worked for me - using the basic authflow instead of enhanced.
I am hoping to supplement the above with some information that other present-day readers using V3 of the SDK may find useful:
On the server, use GetOpenIdTokenForDeveloperIdentityCommand from #aws-sdk/client-cognito-identity to generate the token and send it to the client.
On the client, I was unable to successfully generate credentials with any of the following:
fromCognitoIdentity, from #aws-sdk/credential-providers
GetCredentialsForIdentityCommand, from #aws-sdk/client-cognito-identity
GetCredentialsForIdentityPoolCommand, from #aws-sdk/client-cognito-identity
The following did work, using #aws-sdk/client-sts:
const { STSClient, AssumeRoleWithWebIdentityCommand } = require("#aws-sdk/client-sts")
const client = new STSClient({region: cognitoRegion})
const assumeRoleCommand = new AssumeRoleWithWebIdentityCommand({
WebIdentityToken: openIdToken, // the token your server sends to the client
RoleArn: authRoleARN, // the ARN of the role you set up on AWS Cognito / IAM
RoleSessionName: userId // See note below
})
const credentialsResponse = await client.send(assumeRoleCommand)
// the client apparently expects slightly different property names than the received credentials object
const credentials = {
accessKeyId: credentialsResponse.Credentials.AccessKeyId,
expiration: credentialsResponse.Credentials.Expiration,
secretAccessKey: credentialsResponse.Credentials.SecretAccessKey,
sessionToken: credentialsResponse.Credentials.SessionToken
}
// Example using SES, you may be using different services
const sesClient = new awsSes.SESClient({
apiVersion: "2010-12-01", // yours may be different
region: "us-east-1", // yours may be different
credentials: credentials
})
Note: The AssumeRoleWithWebIdentityCommand docs discuss what you should use for the RoleSessionName.