amplify-js: Auth.currentAuthenticatedUser() does not return Cognito User.
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React
Amplify APIs
Authentication, REST API
Amplify Categories
auth
Environment information
# Put output below this line
System:
OS: macOS 13.0.1
CPU: (10) arm64 Apple M1 Pro
Memory: 126.13 MB / 16.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.18.0 - ~/.nvm/versions/node/v16.18.0/bin/node
npm: 8.19.2 - ~/.nvm/versions/node/v16.18.0/bin/npm
Watchman: 2023.04.03.00 - /opt/homebrew/bin/watchman
Browsers:
Brave Browser: 111.1.49.132
Chrome: 112.0.5615.137
Edge: 112.0.1722.58
Firefox: 111.0.1
Safari: 16.1
npmPackages:
cors: ^2.8.5 => 2.8.5
express: ^4.18.2 => 4.18.2
google-auth-library: ^8.7.0 => 8.7.0
hardhat: ^2.12.2 => 2.12.2
npmGlobalPackages:
@aws-amplify/cli: 11.0.3
corepack: 0.14.1
eas-cli: 2.8.0
nodemon: 2.0.20
npm: 8.19.2
serve: 14.1.2
Describe the bug
Login with google token using Auth.currentAuthenticatedUser() only returns google token like so:
{ “id”: “us-east-1:xxxxx”, “name”: “xxx”, “token”: “xxxxxx” }
Expected behavior
it should return cognito user, or id,access and refresh tokens to create cognito user.
Reproduction steps
- install aws-amplify
- Login with google and get a valid google id token then pass it to Auth.federatedSignIn
- Get the current user with Auth.currentAuthenticatedUser
Code Snippet
// Put your code below this line.
const googleToken = response.credential;
const googleData = parseToken(googleToken);
console.log('googleData:', googleData);
const { email, given_name, exp } = googleData;
Auth.federatedSignIn(
'google',
{
token: googleToken,
expires_at: exp
},
{
name: given_name
}
).then((response) => {
console.log('federatedSignIn res', response);
// Use the Auth.currentAuthenticatedUser() method to check if the user is already authenticated
Auth.currentAuthenticatedUser()
.then((cognitoUser) => {
console.log('cognitoUser:', cognitoUser);
const cognitoToken =
cognitoUser.signInUserSession.accessToken.jwtToken;
// Use the Cognito token to authenticate requests to your backend API
console.log('cognitoToken:', cognitoToken);
})
Log output
// Put your logs below this line
{
"id": "us-east-1:xxxxx",
"name": "xxx",
"token": "xxxxxx"
}
aws-exports.js
No response
Manual configuration
Amplify.configure({
Auth: {
// (required) only for Federated Authentication - Amazon Cognito Identity Pool ID
identityPoolId: 'us-east-1:xxxx',
// (required)- Amazon Cognito Region
region: 'us-east-1',
// (optional) - Amazon Cognito Federated Identity Pool Region
// Required only if it's different from Amazon Cognito Region
identityPoolRegion: 'us-east-1',
// (optional) - Amazon Cognito User Pool ID
userPoolId: 'us-east-1_xxx',
// (optional) - Amazon Cognito Web Client ID (26-char alphanumeric string, App client secret needs to be disabled)
userPoolWebClientId: 'xxx',
// (optional) - Enforce user authentication prior to accessing AWS resources or not
mandatorySignIn: false,
// (optional) - Manually set key value pairs that can be passed to Cognito Lambda Triggers
clientMetadata: { myCustomKey: 'myCustomValue' },
// (optional) - Hosted UI configuration
oauth: {
domain: 'myapp.auth.us-east-1.amazoncognito.com',
scope: [
'phone',
'email',
'profile',
'openid',
'aws.cognito.signin.user.admin'
],
redirectSignIn: `${window.location.origin}/login-google`,
redirectSignOut: 'http://localhost:3000/',
clientId: 'xxxxx',
responseType: 'code' // or 'token', note that REFRESH token will only be generated when the responseType is code
}
}
});
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
is there a way to create valid cognito user with Auth.federatedSignIn response. The response is like so :
{
"identityId": "us-east-1:xx-xxxxx",
"accessKeyId": "xxxx",
"secretAccessKey": "xx/xxx/x+xxxx",
"sessionToken":"xxxxxx"
}
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 20 (8 by maintainers)
Thanks for your response. I have tried possible methods like so:
the method I call for google sign in:
the response from these methods are like so:
and when I call other way of federated sign in like so:
any methods return anything but fall in catch block.
and these are logged at console:
Is there a way to use sessionToken and secretAccessKey?
Sure. I am following Authorization code grant flow.
Below is detailed explanation:
when login with above method (Auth.federatedSignIn), it creates a new user in user pool and returns id_token and access_token when responseType is ‘token’. However i need refresh token too. otherwise i can not create a new CognitoUser object at client side ( so not able to update user attributes as well since not possible to create a valid CognitoUser with id_token and access_token only). Hence i need that REFRESH TOKEN too. According to docs, for example this one in order to get refresh token after federated sign in once should configure responseType as this : responseType: ‘code’.
when you configure responseType: ‘code’ you will get “code” and “state” variables in the url in return. The docs says that it is possible to get id_token, access_token and refresh_token all together by using this “code” with sending a request to /oauth2/token endpoint. It also emphasizes that if the client app that was used requires a secret, the Authorization header for this request is set as “Basic BASE64(CLIENT_ID:CLIENT_SECRET)“, where BASE64(CLIENT_ID:CLIENT_SECRET) is the base64 representation of the app client ID and app client secret, concatenated with a colon. whatever i did, i failed to get those tokens since i got always invalid_request. If I send a new request with already used “code”, this time it returns “invalid_grant”. The sample request is here like so:
Auth.currentAuthenticatedUser() returns only token of provider (here google token). So it is not useful fro me. it is something like this :
Jeremy Glesner addressed this problem here in his article and here in his issue
another issue opened here
Update: I was able to leverage Auth with aforementioned restrictions, by creating following flow:
on the client:
on the backend: 3. verify id_token on the backend (for node.js I’ve used ‘google-auth-library’ npm package) 4. create a cognito user and record real email in some custom attribute, confirm user, set random password 5. send username/ random password to user
on the client: 6. Auth.signIn({ username, password} )
One caveat - I’ve noticed if we were to use Auth.federatedSignIn({ provider : “Google” }) cognito users are created with username google_192301930123 where email attribute could be actual email. When I try to create that, it tells me that username must match look like email. How are users such as google_192301930123 generated? Am I missing something trivial and the above flow is overkill?
Thanks in advance for any input on this matter
Unfortunately I am not able to share repo. yet I have already shared how I configured, logged in with google and tried to get refresh token.
If possible share me a working example of ### authorization code flow when login with google token (or any other social login). I need to see login with google where it returns authorization code that will be later exchanged with cognito tokens (id, access and refresh token).
if you are able to share that working example I could check it and try to understand where i am doing wrong for authorization code flow and share the result here.
any help would be much appreciated
Hi @nadetastic No, I am not saying it’s not creating Cognito User in user pool. It returns id_token and access_token which indicates its creating a new user in user pool.
What is problem here is that I cannot create a new Cognito User instance in front app.
As far as I understand, since i need to update user attributes so I have to create a valid cognito user and cognito session in front. So to be able initiate new cognito session in front app I need to id_token, access_token and refresh_token. Above approach that is exchange code with token using token endpoint always returns invalid_request.
{ "identityId": "us-east-1:xx-xxxxx", "accessKeyId": "xxxx", "secretAccessKey": "xx/xxx/x+xxxx", "sessionToken":"xxxxxx" }But still it seems it is not possible to create a new cognito session with this data
a. returns id_token, and access_token when configured responseType=“token”. I cannot create a valid session with these tokens b. returns code responseType=“code”. Docs states that only way to get refresh token along with other tokens is that using grant_type=“authorization_code”. I am trying to exchange authorization code with token but always get invalid_request. I have asked a lot of place but still stuck here. It is getting boring 😃
ps: It might be related about this issue. #8632
This detail is important to know. Thank you. I should say still i am unable to achieve creating Cognito User with Auth.federatedSignIn({ provider: ‘Google’ }). When I use responseType: ‘token’, It returns only id_token and access_token, there is no refresh token so i could not create a valid Cognito User and cognito session. when it comes to responseType: ‘code’, i am getting invalid_request error from token endpoit for grant_type :authorization_code. this is the config and codes for exchanging code with token.
Yet I am getting error: “invalid_grant” for the same code. I do not understand where i am doing wrong. Any help for this would be much appreciated.