Amplify-js: Login using Identity Provider i.e Google

Created on 28 Mar 2018  路  33Comments  路  Source: aws-amplify/amplify-js

Do you want to request a feature or report a bug?
bug

What is the current behavior?
I still using aws/amazon-cognito-identity-js.
I want to login in my Mobile App to Cognito Pool using i.e my google credentials. When I logged in successfully using my google account I call the following code

AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      'IdentityPoolId': aws_cognito_identity_pool_id,
      'Logins': {
        'accounts.google.com': result.idToken
      }
    });

alert(AWS.config.credentials);

the result: IdentifierId is null.

Question:
How can I authenticate my current google account to AWS-Cognito-Pool?

Thanks

Cognito question

Most helpful comment

@powerful23
I appreciate yours, thanks a lot. But i still wondered why AWS Cognito login stuff is difficult as it is. They explain binding the Cog. Pool with Social Providers as it is a piece of cake, while it is not. And I have seen videos and docs for other Clouds i.e ionic one, the authentication issue especially with FB, google ... is very easy in few lines and calling a function like: FacebookAuthDetails which takes care about adding the user to cloud user pool. If you still have in mind an example that helps in saving my time regarding Cognito User Pool and Identifier it would be very appreciated and helpful.

regards,

All 33 comments

@engharb you need to load your credentials after construct it by AWS.config.credentials.getPromise(). Please check the details here

@powerful23 thank you very much. But I still facing problems. Here I will type the parts of signing-in using the google account and please correct me if there is error.

//# login.ts

loginWithGoogle() {

      this.googleplus.login({})
          .then(
              res => {
                  console.log(res);
                  alert("success");
                  alert(JSON.stringify(res));
                  this.user.loginAwsGoogle(res.idToken, res.displayName);
              }
          ).catch(
              err =>
              {
                  console.error(err);
                  alert("fail");
                  alert(JSON.stringify(err));
              }
      );
  }

then

//# user.ts
loginAwsGoogle(idToken, username) {
    this.cognito.makeGoogleCredentials(idToken, username);
  }

then

//# aws.cognito.ts
getUserPool() {

    return new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool({
            "UserPoolId": aws_user_pools_id,
            "ClientId": aws_user_pools_web_client_id
    });
  }

makeUser(username) {
    return new AWSCognito.CognitoIdentityServiceProvider.CognitoUser({
      'Username': username,
      'Pool': this.getUserPool()
    });
  }


makeGoogleCredentials(idToken, username) {

    AWSCognito.config.credentials.getPromise().then(
        data => {

          AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
            IdentityPoolId: aws_cognito_identity_pool_id,
            Logins: {
              'accounts.google.com': idToken
            }
          });

          alert("Data Correct");
          const user = this.makeUser(username);

            alert(JSON.stringify(data));
            alert(JSON.stringify(user.pool.client));

        },
        error => {
          alert("Data Error");
          alert(JSON.stringify(error));

        }
    ).catch(
        err => {
          alert("Catch Error");
          alert(JSON.stringify(err));

        }
    );

I do not know why I got config->credentials->expired:true is expired????

Do you have a complete example or idea, let me know about your inspiration.

regard.

@engharb There are two "pool" in Cognito: User pool and Identity pool. From the code you provided I think you are actually using Google OpenId to get a federated identity from the Identity Pool. If you want to login in that way, you can either use aws-amplify or write your own code. You can have look at this implementation which may give you some help.

@powerful23
Is not possible to do that using aws-cognito-sdk.js ?
And can u tell me what is the difference between user pool and identity one.
As I know there are connected with each .?

The amazon-cognito-ideneity-js library doesn't handle this case. You need to construct your own CognitoIdentityCredentials and then call getPromise to get it loaded.

Briefly Cognito user pool is just a pool of registered users where you can manage them and identity pool is where the is a pool of authenticated and unauthenticated identities. The source of identities can either be from user pool, or from external provider like Google or Facebook.

Another feature is Cognito OAuth which could enable users to map Google users to Cognito userpool so they can bring external users into their own user pool

You can check Cognito's doc

@powerful23
I appreciate yours, thanks a lot. But i still wondered why AWS Cognito login stuff is difficult as it is. They explain binding the Cog. Pool with Social Providers as it is a piece of cake, while it is not. And I have seen videos and docs for other Clouds i.e ionic one, the authentication issue especially with FB, google ... is very easy in few lines and calling a function like: FacebookAuthDetails which takes care about adding the user to cloud user pool. If you still have in mind an example that helps in saving my time regarding Cognito User Pool and Identifier it would be very appreciated and helpful.

regards,

@engharb yeah it's a bit trivial to figure all the things out. That's why we are developing AWS Amplify as well as Awsmobile CLI to make life much easier for developers. Currently we are working on to integrate the Cognito hosted UI into our library and give users detailed documentation about how to setup with those stuff and that won't be too far. Thanks for your feedback!

@powerful23 Thanks a lot for details. But I have another Idea and I do not know if it works. I tried to get the IdentityId of unauthenticated Facebook on AWS-External-provider and then call getCredentialsForIdentity(). Unfortunately it gives me error as e is not a function.

let params = {
                    IdentityId: AWSCognito.config.credentials.cognito.config.credentials.params.IdentityId,
                    Logins: {
                        'graph.facebook.com': accessToken
                    }

                };

AWSCognito.config.credentials.getCredentialsForIdentity(params, function(err, data) {
                    if (err) {
                        alert(JSON.stringify(err));
                    } // an error occurred
                    else {
                        alert(JSON.stringify(data));
                    }           // successful response
                });

Do you have any Idea if that does work or not?

regards,

@engharb I am not sure as I didn't try this way to get the credentials. But can you make sure AWSCognito.config.credentials is an instance of CognitoIdentityCredentials?

@powerful23 yes it is instance of it.

@powerful23 I would expect when I call

AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
            IdentityPoolId: aws_cognito_identity_pool_id,
            Logins: {
              'facebook provider identity':accessToken
            }
          });

to get a sessionKey contains the three different key, id/access/refreshTokenkey, but unfortunately I do not.
Some references mentioned that but I do not know how they get these three keys.

@engharb that's because the credentials is not loaded at the time when it is constructed. You need to call credentials.get() or credentials.getPromise() to get it loaded.

@powerful23 I also tried

makeGoogleCredentials(idToken, username) {

AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
            IdentityPoolId: aws_cognito_identity_pool_id,
            Logins: {
              'accounts.google.com': idToken
            }
          });

    AWSCognito.config.credentials.getPromise().then(
        data => {
          alert("Data Correct");
          const user = this.makeUser(username);

            alert(JSON.stringify(data));
            alert(JSON.stringify(user.pool.client));

        },
        error => {
          alert("Data Error");
          alert(JSON.stringify(error));

        }
    ).catch(
        err => {
          alert("Catch Error");
          alert(JSON.stringify(err));

        }
    );

the result contains the identityId with expired:true ????!

@engharb hmm.. Maybe try

AWSCognito.config.credentials.getPromise().then(
        data => {
          alert("Data Correct");
          // refresh the credentials
          AWSCognito.config.credentials.refresh((err) => {
             if (err) {
                   console.log(err);
               }
              const user = this.makeUser(username);

             alert(JSON.stringify(data));
             alert(JSON.stringify(user.pool.client));
          });
        },
        error => {
          alert("Data Error");
          alert(JSON.stringify(error));

        }
    ).catch(
        err => {
          alert("Catch Error");
          alert(JSON.stringify(err));

        }
    );

@powerful23
Thank you for your response. I was succeeded in getting the sessionToken, secretAccessKey and accessKeyId.

But I can not automatically create a user or Bind the fb_logged_in user user in Cognito_User_Pool. I tried to follow this issue but no more chance https://github.com/aws/amazon-cognito-identity-js/issues/608.

Do you have any suggestions?

@engharb Yeah I think this is because you are actually creating a federated identity in your identity pool and getting its credential. To bind federated users into your User Pool, you need to setup your web client and identity provider in your user pool console and use Cognito Hosted UI feature. We are working on this feature and there will be a detailed doc on it. I will notify you once it's in our beta version.

@itrestian @powerful23
after getting sessionToken, secretAccessKey and accessKeyId. Is it possible to authenticateUser with these keys instead of 'username and password'?

if yes, How?

regards.

@powerful23
bug

I want to integrate/install Aws-Amplify and use hosted UI in my Ionic mobile project. Project src/Assest contains the following files:
amazon-cognito-identity.min.js, aws-sdk.js ...

I have run $ npm install aws-amplify --save. And when I start run $ ionic cordova run android I got the following exception:

typescript: node_modules/aws-amplify/lib/Analytics/types/Analytics.d.ts, line: 19 
            In ambient enum declarations member initializer must be constant expression. 

      L18:  export declare enum SessionState {
      L19:      START = "START",
      L20:      STOP = "STOP",

those two constants values must be i.e.

START = 1
STOP = 2

in order to solve problem from angular transpile.js

The goal is:
to use AWS-Amplify for authenticating user in login-process (using cognito-user-pool or federated-identifier).
Do i need to install aws-amplify completely?
and Is there a complete example (for ionic_mobile_app and web_app)?

regards,

@engharb you can check this sample. For that error we will make a fix on that, thanks.

@powerful23, you mention adding support for Cognito Hosted UI. Is there an issue tracking this feature? I would be interested in being able to use this.

@dhumeniuk It has been merged in master branch but not published yet. We are going to publish a beta version this week.

@powerful23 thanks a lot for your help and responses. I am eagerly looking for the coming feature utilizing hosted UI (especially in social login). and regarding to the sample that you announced I have successfully configured and implemented the complete login process for our Mobile App and Web App using aws-cognito-sdk.js BUT what still missing is concreted example of how to use the UI (in Mobile/Web app) example?.

Now I am thinking weather to use aws-cognito-sdk.js directly or use aws/amplify.
In case of amplify (as upper layer depends on cognito-sdk.js) I found it easier than using directly the functions in aws-cognito-sdk.js and much less code.

Do you advance me to use aws/amplify or keep working directly with aws-cognito-sdk.js for authentication process?

regards,

@powerful23 I am sorry for asking you frequently. I am able to use

Auth.federatedSignIn(
            'facebook',
            {
                token: authResult.accessToken,
                expires_at:authResult.expiresIn
            },
            {
                email:data.email,
                name:data.id
            }
        );

The result consists of accessKeyId, sessionToken .... The Question :
Is it possible to use this sessionKey or token by using pre-defined function in order to get (idToken, accessToken, refreshToken) and automatically assign/store those values in the session?

I think such a function is needed to be implemented or workaround?

regards,

@engharb I would recommend you to try Aws Amplify as it is designed to provide high level Api for developers. The Auth.federatedSignIn method only works with your federated identity pool to give the federated user a Cognito identity so that he will have the access to your AWS resources. But it won't sign the user in your Cognito User Pool as an external user. I think you should use the Cognito Hosted UI feature so that you will get a Cognito session stored in your localStorage with all these idToken, accessToken and refreshToken.

@powerful23 Hey there, thanx for actively helping out. In Cordova apps, we cannot use the Cognito hosted UI for Google auth. What is the recommended approach for auth with Google?

I went this route with no success.
What do you recommend?

@Birowsky if you only want to get a valid AWS credential from Cognito Federated Identity Pool, then Auth.federatedSignIn would be enough for you to retrieve one once you provide the token from Google. Check this: https://aws.github.io/aws-amplify/media/authentication_guide#enabling-federated-identities and also this: https://docs.aws.amazon.com/cognito/latest/developerguide/google.html#JavaScript

@powerful23 ah, no, I need to end up with a session from a user pool, not an identity pool. Any input there?

I use the user pool hosted ui for the web version of the app. Works nicely. But in Cordova, Google has banned use of the inapp browser, so we have to go with their native flow, which leaves me hanging in terms of how do I utilize the google auth response.

@Birowsky that's beyond my knowledge. @yuntuowang do you know how to sign Google users into user pool through native flow?

Hi @Birowsky, we haven't supported this feature yet. It is on our roadmap. Thanks!

@yuntuowang oh dear.. just spent a day on it :} Good to know it's being considered. Where do I track progress on it? Any vague estimation? Or.. should I ask.. is there nothing I can do by use of the TOKEN or AUTHORIZATION endpoints?

It is hard to comment on the delivery time at this point. Once this feature is released, I will post on this issue! TOKEN and AUTHORIZATION endpoints are for cognito flows.

For anyone interested, I logged the Google auth in Cordova issue here. Let's hope for results as soon as possible. Have a good one!

@yuntuowang I hope that I will be confirmed about the coming features. Is there a way to decode and verify the Identity-Pool sessionToken using i.e PHP-SDK? I solved that for user-pool JWT but not for Identity-pool sessionToken!.

Was this page helpful?
0 / 5 - 0 ratings