Using External Identity Providers with Server Side Authentication
Asked Answered
W

3

9

I'm using the AWS SDK for Go to use Cognito to do server-side authentication. I have sign-up and sign-in done and working using a username and password. I have all three external identity providers configured based off of the documentation as well as redirect URLs and everything else the documentation calls for.

I know how to get the URL for the built Sign Up/Sign In page that Cognito will build for you, and those have the Google/Facebook/Amazon login buttons, but I need to be able to put those buttons on the front end of my site. I don't know how to go about doing that.

Edit: See comment on @Stu's post for detailed reasoning on why the JS SDK answer is marked as the correct answer. This is subject to change, but not for awhile. (tldr; aws go sdk and cognito simply do not support this yet)

Wundt answered 3/10, 2018 at 1:12 Comment(0)
M
4

Your app requirements have grown passed a point of using the cookie cutter Cognito login flow.

I suggest you just handle all your authentication to cognito yourself as seen here: https://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-javascript-examples.html

This way, you can throw a facebook login button on your site like this: https://docs.aws.amazon.com/cognito/latest/developerguide/facebook.html

FB.login(function (response) {

  // Check if the user logged in successfully.
  if (response.authResponse) {

    console.log('You are now logged in.');

    // Add the Facebook access token to the Cognito credentials login map.
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: 'IDENTITY_POOL_ID',
      Logins: {
        'graph.facebook.com': response.authResponse.accessToken
      }
    });

    // Obtain AWS credentials
    AWS.config.credentials.get(function(){
        // Access AWS resources here.
    });

  } else {
    console.log('There was a problem logging you in.');
  }

});

Then get the user like this:

    var data = { UserPoolId : 'us-east-1_Iqc12345',
        ClientId : '12345du353sm7khjj1q'
    };
    var userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
    var cognitoUser = userPool.getCurrentUser();

    if (cognitoUser != null) {
        cognitoUser.getSession(function(err, session) {
            if (err) {
                alert(err);
                return;
            }
            console.log('session validity: ' + session.isValid());
        });
    }

Additional Facebook SDK Info: https://developers.facebook.com/docs/facebook-login/web

Since your going to be going through the motions of setting up the Cognito flow in your application. An additional nugget, I highly recommend you go ahead and set up custom messages with a lambda trigger. https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-message.html

Update: Coming back to this one more time.

https://docs.aws.amazon.com/sdk-for-go/api/service/cognitoidentityprovider/#CognitoIdentityProvider.AdminInitiateAuth

Here you can see a function called AdminInitiateAuth. There are also Functions for attaching users to identity providers. So while Using the JS SDK is probably the easiest, and in my opinion the solution for integrating a web app with cognito. You could clearly handle all your authentication flow, token management, create api's to signin, signout, etc.. server side with the GO SDK

Mani answered 15/10, 2018 at 0:9 Comment(4)
I appreciate the answer, this is correct right now. I was going to add this answer if it wasn't commented. Go SDK for AWS simply doesn't have these features yet. See my comment on @Stu's post for more detail as to why this is the correct answer.Wundt
Your welcome. I added a link at the bottom of my answer on custom messages if you need it.Mani
Coming back to this one more time. docs.aws.amazon.com/sdk-for-go/api/service/… Here you can see a function called AdminInitiateAuth. There are also Functions for attaching users to identity providers. So while Using the JS SDK is probably the easiest, and in my opinion the solution for integrating a web app with cognito. You could clearly handle all your authentication flow, token management, create api's to signin, signout, etc.. server side with the GO SDK.Mani
I use that right now for the username and password authentication. I look at every possible way I could possibly pass it an access token generated by an oauth provider and there is none that I can find. There is only a way to pass it a Cognito generated refresh token.Wundt
P
5

Lets take the Facebook example. When you use the Cognito UI, Facebook hands an OAuth token directly to Cognito for your user. Cognito does some stuff, like checking whether the user already exists, and creating a new one if required, then sends your application an AWS OAuth token.

Now if you want the Facebook button on your own website the authentication happens in a different way. You have to negotiate with Facebook yourself, get an OAuth token back for the user, then hand the access token to Cognito. Cognito will do its stuff and give you back an AWS OAuth token.

So, in short, you need to follow the Facebook SDK setup instructions: https://developers.facebook.com/docs/facebook-login/web

The Facebook SDK puts an access token in your session, which you send to Cognito.

Full details are here: https://docs.aws.amazon.com/cognito/latest/developerguide/facebook.html (See the javascript section)

EDIT: I've just come across AWS Amplify. It has a client side JS library that includes an authentication component. If you are using React, it looks like there is a really simple way to connect Federated Identities (social media logins) with Cognito https://aws-amplify.github.io/amplify-js/media/authentication_guide.html. I've not used the service so can't say too much more about it at the moment.

Poundal answered 11/10, 2018 at 8:29 Comment(2)
Great answer, however right now passing an access token to the Go SDK isn't supported. Spent at least 2 hours digging through the source code, found promising things, but never found exactly what is outlined in the access token tradeoff that the JS SDK gives. I talked to a maintainer of the go sdk on aws on the Gophers slack and he confirmed this, so I submitted a comment on an already-opened issue regarding cognito features. I appreciate your time on this comment. I think the only answer right now is to use the JS client-side sdk :/Wundt
Ah, thats a shame. Thanks for coming back with those details - and good work on getting in touch with the SDK developer!Poundal
M
4

Your app requirements have grown passed a point of using the cookie cutter Cognito login flow.

I suggest you just handle all your authentication to cognito yourself as seen here: https://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-javascript-examples.html

This way, you can throw a facebook login button on your site like this: https://docs.aws.amazon.com/cognito/latest/developerguide/facebook.html

FB.login(function (response) {

  // Check if the user logged in successfully.
  if (response.authResponse) {

    console.log('You are now logged in.');

    // Add the Facebook access token to the Cognito credentials login map.
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: 'IDENTITY_POOL_ID',
      Logins: {
        'graph.facebook.com': response.authResponse.accessToken
      }
    });

    // Obtain AWS credentials
    AWS.config.credentials.get(function(){
        // Access AWS resources here.
    });

  } else {
    console.log('There was a problem logging you in.');
  }

});

Then get the user like this:

    var data = { UserPoolId : 'us-east-1_Iqc12345',
        ClientId : '12345du353sm7khjj1q'
    };
    var userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
    var cognitoUser = userPool.getCurrentUser();

    if (cognitoUser != null) {
        cognitoUser.getSession(function(err, session) {
            if (err) {
                alert(err);
                return;
            }
            console.log('session validity: ' + session.isValid());
        });
    }

Additional Facebook SDK Info: https://developers.facebook.com/docs/facebook-login/web

Since your going to be going through the motions of setting up the Cognito flow in your application. An additional nugget, I highly recommend you go ahead and set up custom messages with a lambda trigger. https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-message.html

Update: Coming back to this one more time.

https://docs.aws.amazon.com/sdk-for-go/api/service/cognitoidentityprovider/#CognitoIdentityProvider.AdminInitiateAuth

Here you can see a function called AdminInitiateAuth. There are also Functions for attaching users to identity providers. So while Using the JS SDK is probably the easiest, and in my opinion the solution for integrating a web app with cognito. You could clearly handle all your authentication flow, token management, create api's to signin, signout, etc.. server side with the GO SDK

Mani answered 15/10, 2018 at 0:9 Comment(4)
I appreciate the answer, this is correct right now. I was going to add this answer if it wasn't commented. Go SDK for AWS simply doesn't have these features yet. See my comment on @Stu's post for more detail as to why this is the correct answer.Wundt
Your welcome. I added a link at the bottom of my answer on custom messages if you need it.Mani
Coming back to this one more time. docs.aws.amazon.com/sdk-for-go/api/service/… Here you can see a function called AdminInitiateAuth. There are also Functions for attaching users to identity providers. So while Using the JS SDK is probably the easiest, and in my opinion the solution for integrating a web app with cognito. You could clearly handle all your authentication flow, token management, create api's to signin, signout, etc.. server side with the GO SDK.Mani
I use that right now for the username and password authentication. I look at every possible way I could possibly pass it an access token generated by an oauth provider and there is none that I can find. There is only a way to pass it a Cognito generated refresh token.Wundt
T
1

It's now possible with identity_provider prop in oauth2/authorize request

looks like that in my code

const query = stringify({
    response_type: 'code',
    redirect_uri: tokenRedirectUri,
    state: stateEncoded,
    client_id: clientId,
    identity_provider: platform,
})


return `https://auth.${domainName}/oauth2/authorize?${query}`

where platform is Google/Facebook/other OIDC provider etc.

That's only url, you'd need to make button by yourself, but it redirects directly to provider consent

Thimblerig answered 7/5, 2020 at 20:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.