-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Amplify missing the ability to programmatically create a user session using Cognito (id, access, refresh) tokens #8632
Comments
Upon further investigation, it does appear you can create a CognitoUserSession with the id/access/refresh tokens using the amazon-cognito-identity-js package with the code below, but Amplify doesn't recognize that the session exists. import * as AmazonCognitoIdentity from "amazon-cognito-identity-js";
// passing a valid cognito response url with authorization_code and state
Auth._oAuthHandler.handleAuthResponse(url).then((resp) => {
// using the id, access and refresh tokens provided by the AuthHandler:
const AccessToken = new AmazonCognitoIdentity.CognitoAccessToken({
AccessToken: resp.accessToken,
});
const IdToken = new AmazonCognitoIdentity.CognitoIdToken({
IdToken: resp.idToken,
});
const RefreshToken = new AmazonCognitoIdentity.CognitoRefreshToken({
RefreshToken: resp.refreshToken,
});
const sessionData = {
IdToken: IdToken,
AccessToken: AccessToken,
RefreshToken: RefreshToken,
};
const session = new AmazonCognitoIdentity.CognitoUserSession(
sessionData
);
}); Once the above code completes successfully, running Auth.currentAuthenticatedUser()
.then((user) => console.log(user))
.catch((err) => console.log(`Not signed in ${err}`)); Is there anyway for amplify.auth to pick up the CognitoUserSession, or to do something similar through Amplify? This looks similar to #6555. |
Continuing to work with this --it seems like you can get Amplify to pick up the session if you cache it in localstorage as described in #825 (very convoluted). Been working all morning to find a cleaner way to do this using either Amplify or the amazon-cognito-identity-js package; the best I've come up with so far (which relies on the code in my last post) is this: // create an object with the UserPoolId and ClientId
var poolData = {
UserPoolId: <<UserPoolId>>,
ClientId: <<ClientId>>,
};
// pass the poolData object to CognitoUserPool
var userPool = new AmazonCognitoIdentity.CognitoUserPool(
poolData
);
// create an object containing the username and user pool. You can get the username from the accessToken
// using the AmazonCognitoIdentity.CognitoAccessToken class (from previous post)
var userData = {
Username: AccessToken.payload.username,
Pool: userPool,
};
// create a cognito user using the userData object
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(
userData
);
// set the cognito user session w/ the session created in my previous post from
// calling the AmazonCognitoIdentity.CognitoUserSession() class with the Cognito tokens
cognitoUser.setSignInUserSession(session); Now, Amplify will return the authenticated user correctly. Is there a cleaner/simpler way of doing this? If Amplify/Auth are already configured, and you have the CognitoUserSession separately, it seems as though there should be a single method that just does the above for you -- rather than making the developer have to spend hours upon hours figuring all this out. |
You seem to have solved your use case. Our team will consider your feature request in the future for Auth |
Hello everyone, could you check my post here: #9917 |
@jglesner Hey mate, could you help here? |
I documented my approach in a medium blog. https://medium.com/codex/how-to-process-an-aws-cognito-authorization-code-grant-using-aws-amplify-b49d9ee052ca Not 100% sure why you’re getting ‘undefined’; I know typescript takes issue with the fact that _oAuthHandler is private. There are ways to bypass this I’ve read and access the method, but it’s not recommended. I submitted a feature request to make this method public (linked earlier in this issue). |
@jglesner I already red your blog yesterday and congratulations mate, it is really helpful and nicely written article! Thanks a lot. Regarding my issue, I'm not using typescript, just ReactJs and I really can't figure out why this is happening..
I would like simple to try this, if this works or not, so how could I pass this ? I'm aware that scenario is not recommended, but could you help here a little bit? I would be really thankful! Thanks in advance Jeremy |
Based on the error, my first guess would be that Amplify/Auth is misconfigured. Otherwise, Auth._oAuthHandler wouldn't be undefined. I looked at your post #9917, and I don't see that you've provided your oauth config to Amplify.configure({ ... }). I've pasted the oauth segment below; you can see how this snippet fits in the overall Amplify config as shown in the documentation. Can you confirm whether you've configured Cognito >> User Pools >> App Integration, and included that information w/ your configuration?
You can |
@jglesner Thanks a lot Jeremy, this post was helpful a lot ! But I have one issue and I'm wondering how could we solve this... Actually if I close the tab or the browser, Aplify somehow lose configuration and it says:
Have you face this issue already or ? Thanks in advance |
I assume you’re doing oAuth Federated login … but it sounds like a separate tab/browser is being opened? Are you doing this in a standard web app or a js mobile app? |
Need a way to programmatically create a user session using Cognito (id, access, refresh) tokens. This will be a huge plus for advanced workflows including allowing users to log in to Chrome extensions using amplify. @evcodes @abdallahshaban557 is it possible to mark this as a feature request? |
I'm currently needing this feature as well. We have a shell app that does the login and passes the tokens to the micro UI applications. One of which is actually an SSR application. The server has no context for auth other than the tokens and it would be a terrible UX to make the user login again. So even the local storage hack won't work for us. I can get away with forcing the calls to have the correct headers, but that doesn't stop the library from fussing about no "active users" when trying to get subscriptions. |
Hey, @jglesner ! Thanks a lot mate for your contribution here! I'm interested in this line of code:
so basically if we would like to achieve refresh token implementation we would need to keep this |
Thank you very much @jglesner for your implementation it saved me a lot of time.
|
Hello @jglesner ! I tried to replicate what you did thanks to your code. My first question is : what's the value of the "url" parameter ? I currently have "https://.com/login/code=<AUTH_CODE>&state=. Would it work with it ? I also have a problem : once I do the Auth._oAuthHandler.handleAuthResponse(url).then((resp) => { ............. });, my tokens have no value and if I tried to make a console.log(resp), I just have a "state:undefined". Do you have an idea about what could be wrong ? |
Hello @DefinitelyNotANugget The URL is constructed/vended by cognito; it’s partially the redirect_uri that you set up in the Cognito Dashboard user pools > App integration > App client settings. Cognito appends a unique code grant to the URL that is used to retrieve the tokens. After sign-in via the Hosted UI, Cognito redirects the user to that URL. You have to intercept it. Amplify natively uses a If the URL isn’t legit, handleAuthResponse won’t work. This method calls cognito with the code grant to return your app tokens. |
I implemented @kalousmichal solution in typescript but on the very first load |
Before opening, please confirm:
JavaScript Framework
React
Amplify APIs
Authentication
Amplify Categories
auth
Environment information
Describe the bug
I'm working on a straight react js mobile application using cordova, and want to use Amplify with Social Sign On. I can't reliably use deep links, and need to handle the authentication flow within the app itself. I'm able to get to the point where I receive the authorization code grant URL from Cognito. But there doesn't appear to be a way in Amplify to create the user session using the tokens provided by Cognito.
This functionality seems to have once existed in amazon-cognito-auth-js with the
parseCognitoWebResponse()
method. However, there is only one reference to CognitoAuth client in Auth.ts on line 209. It does not seem that you can retrieve a CognitoAuth client from the Auth object. So it would seem this capability is no longer supported anymore.Amplify's
Auth._oAuthHandler.handleAuthResponse()
function does parse a Cognito authorization code grant url against the oauth2/token endpoint, and returns the idtoken, refreshtoken and accesstoken, but thehandleAuthResponse
function does not store these tokens or create a Cognito User Session. There does not appear to be any way to create a User Session, using these tokens, via Amplify, the amazon-cognito-identity-js library, or the AWS JS SDK v3 (Cognito Identity Provider).This issue was acknowledged by the Amplify team in a comment by @powerful23 in #825 --- there should be a way to create a session apart from having to use the urlListener, and worst case, provide tokens to Amplify to create a user session. The Amplify team coded a rudimentary capability, but it was never released out of beta. #825 seems to have been closed without any resolution.
Based on comments in #825, it may be possible to trick Amplify by pushing these tokens into storage, but that's super hacky.
Am I missing something?
Expected behavior
I would expect the Amplify Authorization library to offer some mechanism to both (1) parse the authorization code grant response from Cognito, and (2) provide a way of creating a user session with the provided tokens without the reliance on urlListener. Just having the first by itself is not helpful. The lack of being able to create a user session greatly constrains Amplify's usefulness as soon as you go offroad.
Reproduction steps
Try to create a Cognito user session without urlListener, or using
Auth._oAuthHandler.handleAuthResponse()
. It doesn't appear to be possible.Code Snippet
// Put your code below this line.
Log output
aws-exports.js
No response
Manual configuration
No response
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
No response
The text was updated successfully, but these errors were encountered: