Skip to content
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

Signing into a user pool with facebook/google, user not persisting? (REACT-NATIVE) #1143

Closed
VicFrolov opened this issue Jun 29, 2018 · 68 comments
Assignees
Labels
Auth Related to Auth components/category question General question React Native React Native related issue

Comments

@VicFrolov
Copy link

We are using Auth.signIn for users in our user pool, and all is working as expected. We use an idToken to authorize users. We have all custom UI, and are using react-native and Amplify.

When we tried setting this up to log in with Facebook/Google, we are running into issues. Our two options were:

  1. Use Cognito web portal:
    a) Open up the web view for Cognito -> Federation Identity Providers.
    b) When they click the facebook, we get back either a code, or we get tokens, e.g. idToken/accessToken.
    c) the problem is now signing them in with Amplify.

  2. Use Amplify Auth.federatedSignIn
    a) this works, and when we sign them in, we get a user object with various details.
    b) the problem is, when we call Auth.currentSession(), it says there is no signed in user.
    c) this might be related to B, as we need to wrap the app in Authenticator, but this doesn't seem to be supported by Amplify yet?
    d) This leads to another problem, even if this works, we dont get any idTokens and would not be able to hit our endpoints

We are stuck at finding a solution where we use our own UI/components, and are unable to think of a way to sign the user in, even though both options 1 and 2 "work" up until a certain point.

@powerful23
Copy link
Contributor

Hi thanks for your feedback.

For the first option, do you mean using Cognito hosted UI to get you sign in with Facebook/Google?

For the second option, you are actually signing with Facebook/Google and get a AWS credentials from Cognito Federated Identity pool, for details: https://github.com/aws/aws-amplify/wiki/FAQ#how-can-i-get-jwt-token-when-using-amplify-to-get-federated-users-login

Also we are working on to provide a session object when using Auth.federatedSignIn through Auth.currentSession.

@powerful23 powerful23 self-assigned this Jun 29, 2018
@powerful23 powerful23 added question General question Auth Related to Auth components/category labels Jun 29, 2018
@VicFrolov
Copy link
Author

Hi @powerful23

After doing some more research and reading up on docs, the behavior I would like is the following:

  1. User hits on the custom Facebook button we have created
  2. this signs the user in somehow to amplify (by using identity pool federation, and not federated identities), and we create a user pool entity.

It seems there's no way to currently do this, correct? Because even if I wanted to use the HOC authenticator component, I couldn't as it is not compatible with react native quite yet?

Any suggestions? I was able to create a federated identity login, and then through some hacky steps get an idToken, but the problem is we also want to create a user in the cognito user pools.

@reggie3
Copy link

reggie3 commented Jul 13, 2018

@VicFrolov I am running into the same problem. @powerful23 , this issue seems also seems to prevent the facebook (and google) user group from being populated. This then cascades into the inability to use user group based authentication techniques in AWS AppSync.

@powerful23
Copy link
Contributor

Related to #585
For now as I know you have to use Cognito Hosted UI to create external federated users in the cognito user pools. Unfortunately this feature is not implemented in React Native. We have this in the road map.

@VicFrolov
Copy link
Author

VicFrolov commented Jul 17, 2018

It's hard to identify, as the docs indicate you can indeed use HOC components, and Cognito hosted UI in react native. I tested it without any styling, and the cognito hosted UI did appear by using aws-amplify-react-native with a HOC component wrapping the entire test project app. I was greeted with a login page.

The concern I have, if this does work and isn't just the UI portion, is how to then style each component, as my login/signup pages are in separate components/views.

e.g. in the docs for Authentication, it has this line:

import { withAuthenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native';

@flaviocordova
Copy link

The missing userSession when using federatedSignIn is critical to me too... :(
Any chances it could be released soon ? 😄

Meanwhile, is there any workaround I could use ? 😟

@oste
Copy link

oste commented Aug 7, 2018

My org is also wondering about this. When a user signs up via facebook there is no record in the user pool. Can someone point me to docs on how this can work? I have not found anything and this is a deal breaker for using Amazon Cognito.

A custom code work around would be fine, I just have not seen any information on creating a user record with a federated auth. Is this possible?

Thanks

@reggie3
Copy link

reggie3 commented Aug 7, 2018 via email

@VicFrolov
Copy link
Author

You have to use Hosted UI, however it is not compatible with react-native, nor is ample customization. The HOC itself is react-native compatible, but not identity providers.

We're most likely going to get rid of cognito all together, and just use federated identities as this is too much of a headache/waiting game.

It's a shame, because this seems like a core feature.

@tobiastornros
Copy link

Any update on when this will be supported on React Native without hosted UI? Next month, end of this year or next year?
Can we help or is there some internal Cognito problem that needs to be solved before?

Related to #311 , #513 and PR #878

@ganap
Copy link

ganap commented Aug 27, 2018

Why is the AWS Amplify team silent on this? Do you even have a plan to fix this? This should be a high priority item, if you claim that federated auth works in React Native with Amplify!

@powerful23
Copy link
Contributor

Currently we are working with the Cognito team to provide the api to sign in the User Pool with federated providers without using the Hosted UI. We are not sure about when it will be implemented but we will try to make it ASAP.

@VicFrolov
Copy link
Author

So I still don't understand how one could use the Hosted UI for facebook/google with amplify, and after they get the tokens from the callbacks, to have the user be logged in via cognito on amplify, with no HOC components.

@powerful23
Copy link
Contributor

@VicFrolov when calling Amplify.configure(), the library will check if oauth is configured and if yes, it will try to parse the current url which contains the tokens, and then construct a session based on those tokens. You can call Auth.currentAuthenticatedUser() when the page is loaded to tell whether the user is logged in. I have a pr about how to use the currentAuthenticatedUser method: https://github.com/aws-amplify/amplify-js/pull/1450/files

@VicFrolov
Copy link
Author

VicFrolov commented Aug 27, 2018

@powerful23 Hmmm, interesting! But if I were to be using react native + safari view for example, the user taps the facebook button in our app, it opens up safari view, and shows Cognito's hosted web UI.

The user then hits the cognito facebook button, they confirm on facebook, and get the callback URL + redirect, how do I pass the url in, for it to parse it and construct a session?

@powerful23
Copy link
Contributor

@VicFrolov good question. Unfortunately for now Amplify doesn't support that but you can do a workaround by using amazon-cognito-auth-js to parse the url like Amplify does. If you look into the auth module: https://github.com/aws-amplify/amplify-js/blob/master/packages/auth/src/Auth.ts#L173 and https://github.com/aws-amplify/amplify-js/blob/master/packages/auth/src/Auth.ts#L149

@VicFrolov
Copy link
Author

VicFrolov commented Aug 28, 2018

@powerful23 So just to confirm, I can use this workaround to log users into cognito via federated identities, using amplify and can then use Auth.currentUser() and stuff, right?

I just don't see where I can pass in the url that is returned to me from the callback, or where it is reading it.

If this is the case though, this is incredible news!

@dsinai14
Copy link

@VicFrolov Till we'll have the api to create a user in the user pool from Federated token, we used the following workaround:

Used react-native-app-auth to identify with cognito using oauth 2.0, it will open the browser and ask for a login then return the user to our app where we get the parsed tokens

We are using our own buttons in the ui but calling the Facebook/Google authorize point explicitly

Hope it makes sense

@VicFrolov
Copy link
Author

@dsinai14 thank you for this!

I would ideally prefer to remain within the Amplify framework, if powerful23 was suggesting I can use amazon-cognito-auth-js in unison with Amplify, but if not this sounds like a solid alternative :)

@powerful23
Copy link
Contributor

@VicFrolov yes. So once you parse the url successfully, you can use methods in the Amplify Auth module like currentSession or currentAuthenticatedUser. The root reason for this happening is that Amplify, amazon-cognito-auth-js and amazon-cognito-identity-js share the same cache items so as long as one of the library stores those tokens into the cache, the other ones can work by reading it.

@VicFrolov
Copy link
Author

@powerful23 oh my goodness, this is amazing, I had no idea they shared cache. This makes me very happy.

Also, slightly off topic but since we're discussing cache, is there any risk / downside to manually refreshing the tokens, and saving it to async storage in the correct place? We need to sometimes force token refreshes when users are changed to a group, as it adjusts their permissions.

Regardless, thank you for all of this information powerful23, I'm happy I get to remain with Amplify and not have to do a massive refactor of our SDK + front end authentication.

@powerful23
Copy link
Contributor

@VicFrolov as I know there is no risk refreshing tokens manually.

@VicFrolov
Copy link
Author

VicFrolov commented Aug 30, 2018

@powerful23 Hey so unfortunately this doesn't seem to be working for me. I was able to get cognitoAuthClient to log a user in via facebook callbackURL after using the hosted UI:

// some set up above
cognitoAuthClient.userhandler = {
      onSuccess: function(result) {
        console.log(result, 'Sign in success');
      },
      onFailure: function(err) {
        console.log('Error!' + err);
      },
    };

await cognitoAuthClient.parseCognitoWebResponse(callbackURL);

if I then called

cognitoAuthClient.isUserSignedIn()

it returned true, and

cognitoAuthClient.getCurrentUser()

returned the appropriate user. However, if I called

await Auth.currentAuthenticatedUser();

after the above, it returned "Not Authenticated".

And vice versa, if I logged a user in via Amplify with username/pass, it worked for Amplify, but if I called cognitoAuthClient.isUserSignedIn(), I would get false.

Even more strange, I tried to see what user I was getting with:

  const userPool = new CognitoUserPool(poolData);
  userPool.storage.sync(function(err, result) {
    if (err) {
      console.log(err, "error")
    } else if (result === 'SUCCESS') {
      var cognitoUser = userPool.getCurrentUser();
      console.log(cognitoUser, "some user")
    }
  });

And the above was in sync with amplify, but not CognitoAuth.

@powerful23
Copy link
Contributor

@VicFrolov did you check the localStorage after you are logged in?
The Cognito Auth Client will cache those tokens with the function: https://github.com/aws/amazon-cognito-auth-js/blob/master/src/CognitoAuth.js#L404
Can you confirm there is an item with the key LastAuthUser in your cache? Because when you call Auth.currentAuthenticatedUser(), it will try to get this item which happens here: https://github.com/aws-amplify/amplify-js/blob/master/packages/amazon-cognito-identity-js/src/CognitoUserPool.js#L125

Also please make sure you are using the default localStorage.

@VicFrolov
Copy link
Author

VicFrolov commented Aug 30, 2018

@powerful23 Hmmm yes you're right, they are not being stored at all in local storage. For some reason, after successfully "signing in" via google or facebook, I get:

cognitoAuthClient.isUserSignedIn() // Google_1234567890
cognitoAuthClient.getCurrentUser() // true

but when I print out all the local storage keys, they are not being generated (neither key or value). However, if I log in via amplify, it creates:

"@MemoryStorage:CognitoIdentityServiceProvider.clientId.username.idToken"
"@MemoryStorage:CognitoIdentityServiceProvider.clientId.username.refreshToken"
"@MemoryStorage:CognitoIdentityServiceProvider.clientId.username.accessToken"
"@MemoryStorage:CognitoIdentityServiceProvider.clientId.LastAuthUser"

On amplify logout, the above keys and values are removed.

I didn't change anything to localStorage, but maybe I need to set it?

Here is my cognitoAuthParams:

    const cognitoAuthParams = {
      ClientId: 'clientId',
      UserPoolId: 'poolId',
      AppWebDomain:
        'https://my-app.auth.us-west-2.amazoncognito.com',
      TokenScopesArray: [
        'phone',
        'email',
        'profile',
        'openid',
        'aws.cognito.signin.user.admin',
      ],
      RedirectUriSignIn: 'https://www.google.com',
      RedirectUriSignOut: 'https://www.google.com',
      IdentityProvider: 'Google',
    };

I didn't set anything for Storage or AdvancedSecurityDataCollectionFlag.

Might as well post my functions:

async googleSignIn(callbackURL) {
    try {
      const AmplifyUser = await Auth.currentAuthenticatedUser();
      console.log(AmplifyUser, '\nAMPLIFY LOGGED IN USER');
      return AmplifyUser;
    } catch (e) {
      try {
        await this.cognitoAuthClient.parseCognitoWebResponse(callbackURL);
        console.log(this.cognitoAuthClient.getCurrentUser()); // returns correct username
        console.log(this.cognitoAuthClient.isUserSignedIn()); // returns true
      } catch (err) {
        console.log(err, 'error parsing cognito web response');
      }
    }
  }

and in the constructor of my class, I set the pre-mentioned params to:

this.cognitoAuthClient = new CognitoAuth(cognitoAuthParams);
    this.cognitoAuthClient.userhandler = {
      onSuccess: result => {
        console.log(result, 'Sign in success');
      },
      onFailure: err => {
        console.log(err, 'Sign in error');
      },
    };

@powerful23
Copy link
Contributor

@VicFrolov You can debug by setting a break point at https://github.com/aws/amazon-cognito-auth-js/blob/master/src/CognitoAuth.js#L404 to see how the CognitoAuth client stores your token after you logged in with Google.

@wdevon99
Copy link

wdevon99 commented Sep 10, 2018

Finally got it working!!!! Thanks :) @VicFrolov and @powerful23

@Daanoz
Copy link

Daanoz commented Oct 3, 2018

If you don't want to switch code to the PR branch, this workaround also works for me (just place it in some location that's get run before any auth requests):

CognitoAuth.prototype.createCORSRequest = function (method, url) {
    var xhr = new window.XMLHttpRequest();
    xhr.open(method, url, true);
    return xhr;
};

@shawnpetros
Copy link

@VicFrolov, did you ever put together an example repo with this flow for mobile login with social that federates? I am starting a new RN app (using expo) and am wanting to signin/register a user with FB and allow the user to be provisioned for GraphQL calls using amplify api, but the way I have FB signin set up is calling .federatedSignIn() with the user but no user is created in Cognito leading to no user signed in when trying to call API mutations. If I could get past this Cognito hurdle I would be in a good place

@powerful23, are we still waiting for Cognito/Federated Identities on RNative? Any updates on when?

@agathao
Copy link

agathao commented Jan 24, 2019

I am interested on the same information

@crcommons
Copy link
Contributor

I'm also looking for an update on if/when federated identities will work with cognito user pools and react native @powerful23 (without doing the workaround described above).

@cloudy-ninja
Copy link

@VicFrolov
Your solution and fork are not working for me.
@mikaelwecode, @wdevon99
How did you solve the problem?

@ngocketit
Copy link

Anyone, does the above problem happen only with React Native or with Web as well?

@Farhadkm
Copy link

Farhadkm commented Feb 8, 2019

Thanks to @VicFrolov and @powerful23 I was able to make the login/register work with react native. I had to read everything multiple times to figure out so here are the steps that I took in case anyone is wondering (I am assuming you do have the facebook account and user pool configured):

  1. get the custom UI url from user pool. Then used webview to redirect the user to go to the link on the application when they click on login with facebook. (you can use other apps to take the user to the facebook login page, webview just gives it a much nicer flow in my opinion).
  2. as redirect url I have put my own app's url and then used deep linking to capture the return call (since I am using react-native-init and not expo my redirect link looks like myapp://login).
  3. after capturing the url I used the cognitoAuthClient.parseCognitoWebResponse(webResponse) function of amazon-cognito-auth-js. You do have to fixed the current issues of the amazon-cognito-auth-js library as mentioned above or just use the VicFrolov git fork of the library.
  4. set the storage of cognitoAuthClient of amazon-cognito-auth-js and Auth of amplify to common store using { StorageHelper } of '@aws-amplify/core' as mentioned above by powerful23.

@jfoldenburg
Copy link

@Farhadkm I've found that the issue I'm having is that the cognitoAuthClient and Auth of amplify don't seem to be using the same store. Any insight on how to use { StorageHelper } would be appreciated. I see that you can set both in the storage key of the objects used to configure both. However what do you specify to make sure they both are using the same? Do you create an instance before referencing it and then pass it to both?

@Daanoz
Copy link

Daanoz commented Apr 12, 2019

For the ampilify setup you can just give as a key in the config:

const awsConfig = {
    Auth: {
      identityPoolId: ``,
      region: '', 
      userPoolId: `,
      userPoolWebClientId: '',
      storage: new StorageHelper().getStorage()
    }
}

Then, when creating the cognitoAuthClient make sure to pass the same instance:

const cognitoAuthClient = new CognitoAuth( {
  ClientId: awsConfig.Auth.userPoolWebClientId,
  UserPoolId: awsConfig.Auth.userPoolId,
  AppWebDomain: ..,
  TokenScopesArray: ...,
  RedirectUriSignIn: ...,
  RedirectUriSignOut: ...,
  Storage: awsConfig.Auth.storage
});

@jfoldenburg
Copy link

Thank you!

@juanbustamanteIntegra
Copy link

@Farhadkm How do you capture the custom UI URL? Also, do you have an example code? I'm having trouble with handling the callback after the login.

@Vahn84
Copy link

Vahn84 commented Jul 30, 2019

Is this still open???????????

@pbirsinger
Copy link

I also really would like this to just work w/o the hosted UI w/o doing that wacky workaround

@askdesigners
Copy link

How is it possible that such a standard thing is so poorly supported... For all the problems cognito solves it easily creates just as many if not more. Really shitty tool.

@chakrihacker
Copy link

Any update on this?

@giulioambrogi
Copy link

Hitting the same problem on 6.3.1

@askdesigners
Copy link

The solution is to not use Amplify or Cognito. They are both awful products with no support at all.

@saadahmadabbasi
Copy link

@powerful23 any update on this pls? any roadmap for this?
Dont make us all think its unsupported :)

Currently we are working with the Cognito team to provide the api to sign in the User Pool with federated providers without using the Hosted UI. We are not sure about when it will be implemented but we will try to make it ASAP.

@github-actions
Copy link

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 10, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Auth Related to Auth components/category question General question React Native React Native related issue
Projects
None yet
Development

No branches or pull requests