How to authenticate user using identity providers in User Pool
I need to authenticate users using federated identity providers in User Pool (docs). I can get access token from google or facebook but I don't know what should I do with this token to authenticate user in User Pool. Can you please give me an example how to do it using js sdk or link to API Reference method?
I have a similar use case, I haven't found any sample code or docs. Is there anyone that can help us?
EDIT: Are you looking for Federated Identities on Identity Pools or Federation on User Pool? These are two different scenarios.
I want to provide the ability to authenticate via Facebook or Google and then authenticate the user on my User Pool to obtain a Token ( so in my case would be Federation on User Pool ). What about you?
I have a very similar problem. However I think in such case the approach should be oposite (as previously I used Auth0 and that was very similar):
- Define custom attribute in user pool to store FB access token.
- Define attribute mapping for Facebook integration to map access_token to that custom attribute.
- Authenticate user with User Pool by specifying Facebook as authorizer (
https://<yourdomain>.auth.<region>.amazoncognito.com/oauth2/authorize?identity_provider=Facebook&redirect_uri=https://<yourpage>&response_type=token&client_id=<your_user_pool_app_id>&scope=openid%20email%20profile%20aws.cognito.signin.user.admin&state=<verify_string>) - unfortunately I did not find equivalent method in Cognito Identity JS - onlyauthroizeUser()variant uses username+password athentication - Then you can obtain FB access token with AWS SDK from User Pool attributes.
Would be great to have this flow covered with the lib API (this feature was added not that long ago to User Pools - federated authenticators, so I guess libs are not yet updated).
@danilotorrisi I'm looking for Federation on User Pool too
+1
+1
+1
I've explained the process here:
https://github.com/aws/amazon-cognito-identity-js/issues/500
You would have to use the Auth sdk to interact with the authorize/token endpoints. https://github.com/aws/amazon-cognito-auth-js/
That would have you login with Facebook if Facebook is an identity provider for your user pool. A corresponding user is created in your user pool and the auth SDK saves that username and tokens in a local storage location (same location where this SDK retrieves it from). By using use case 16 in this SDK you can retrieve that user and the session containing the tokens.
@itrestian Thank you for the answer. Is it posible NOT to use built-in AWS UI for signing up and signing in users? I want to use my own UI. Is it possible to authenticate user in User Pool by Facebook access token?
@itrestian This is not the answer, as stated above we want to authenticate just with FB access token, not to trigger the external UI flow.
@ildar-icoosoft Please see my answer - by specifying identity_provider URL argument you automatically trigger the social flow. You can then also create a simple <iframe> to run it in the background and use postMessage() to send acquired tokens to parent.
Would also like to see fed integrated in user pools. Any update on how this might be achieved / when the libs are being updated? Where might I find aws docs and examples?
@rafalwrzeszcz, we do not accept Facebook token directly as of now. But if you hit /authorize endpoint with identity_provider=Facebook and the end user is already logged in, it will not show the Facebook UI to the end user (except the first time, when they need to grant the permissions to the Facebook App). Isn't this simpler as you do not have to deal with Facebook tokens? Any feedback is welcome on this.
@rachitdhall: Totally, this is even the flow I proposed in my first post here. The only issue is that the lib doesn't provide possibility to do that. By specifying provider option I don't mean to add handling of Facebook token, but just URL identity_provider in the lib config so it could redirect to /authorize?...&identity_provider=Facebook. This way we could get a Cognito access/ID token automatically from hosted page configured with Facebook federation.
@rachitdhall I use the cognito authentication within a native application and it makes things easier to just take the facebook sdk to get the Access Token and use this to register / authenticate on cognito (which can validate the access token at facebook in the background) . because on native applications, redirections don't work so well..
@rafalwrzeszcz Thank you! It works for me.
I have a function googleLogin, that opens https://<yourdomain>.auth.<region>.amazoncognito.com/oauth2/authorize?identity_provider=Google&redirect_uri=https://<redirect_page>&response_type=token&client_id=<your_user_pool_app_id>&scope=openid%20email%20profile%20aws.cognito.signin.user.admin&state=<verify_string> in popup window. <redirect_page> uses postMessage to send acquired tokens to parent script. Parent script gets tokens, saves tokens to cache and gets Cognito credentials.
Here is my code:
googleLogin() function. Pay attention to lines:
cognitoUser.signInUserSession = cognitoUser.getCognitoUserSession(tokensData);
cognitoUser.cacheTokens();
without them the session disappears after the page is refreshed
public googleLogin(): Observable<any> {
return new Observable(observer => {
let authHost = 'https://<some_name>.auth.us-east-1.amazoncognito.com';
let identityProvider = 'Google';
let redirectUri = 'https://localhost:8080/assets/oauth/receiver.html';
let responseType = 'TOKEN';
let clientId = '<app_client_id>';
let state = 'some_state';
let scope = 'profile email openid';
let authUrl = `${authHost}/oauth2/authorize?identity_provider=${identityProvider}&redirect_uri=${redirectUri}&response_type=${responseType}&client_id=${clientId}&state=${state}&scope=${scope}`
window.open(
authUrl,
"awsGoogleAuth",
"location,toolbar,resizable,scrollbars,status,width=600,height=600"
);
window.addEventListener("message", res => {
let tokensData = res.data;
let token = tokensData.IdToken;
let payload = token.split('.')[1];
payload = JSON.parse(atob(payload));
let username = payload['cognito:username'];
let userPoolId = <user pool id>;
let clientId = <client id>;
AWS.config.credentials.params.Logins['cognito-idp.' + awsConfig.region + '.amazonaws.com/' + userPoolId] = token;
AWS.config.credentials.refresh(err => {
if (err) {
return observer.error(err);
}
let poolData = {
UserPoolId : userPoolId, // Your user pool id here
ClientId : clientId // Your client id here
};
let userPool = new AWS.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
let userData = {
Username : username,
Pool : userPool
};
var cognitoUser = new AWS.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.signInUserSession = cognitoUser.getCognitoUserSession(tokensData);
cognitoUser.cacheTokens();
console.log("Amazon Cognito Identity", AWS.config.credentials.identityId);
observer.next(AWS.config.credentials.identityId);
});
}, false);
});
}
<redirect_page> - Page in popup window:
<script>
function getHashValue(key) {
var matches = location.hash.match(new RegExp(key+'=([^&]*)'));
return matches ? matches[1] : null;
}
window.opener.postMessage({
AccessToken: getHashValue('access_token'),
ExpiresIn: getHashValue('expires_in'),
IdToken: getHashValue('id_token'),
TokenType: getHashValue('token_type')
}, '*');
window.close();
</script>
@davideickhoff you can try cordova in-app-browser plugin for Facebook. But it will not work with Google. Google denied access from web view
I get an error on - CognitoUser does not exist on CognitoIdentityServiceProvider. If I get CognitoUser from amazon-cognito-identity-js it gives an error about no method cacheTokens() on cognitoUser .
var cognitoUser = new AWS.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.signInUserSession = cognitoUser.getCognitoUserSession(tokensData);
cognitoUser.cacheTokens();
@ajaxon it looks like you didn't included amazon-cognito-identity.js script. This should fix this error:
import "amazon-cognito-identity-js/dist/amazon-cognito-identity.js";
import "aws-sdk";
Hmm yeah my imports are:
import {CognitoUserPool, CognitoUserAttribute, CognitoUser, AuthenticationDetails} from 'amazon-cognito-identity-js'; import * as AWS from 'aws-sdk'; import {CognitoIdentityCredentials} from "aws-sdk";
So this is related to the typescript types file. I'll take a look at fixing that.
@ajaxon try to replace import "amazon-cognito-identity-js"; to import "amazon-cognito-identity-js/dist/amazon-cognito-identity.js"; It should help
I just edited the index.d.ts file to include the methods I needed. Everything is working now , however when I make a social login request I only get back the idToken and accessToken without the refreshToken. How are you keeping the social user token refreshed?
@ildar-icoosoft thanks for the code but is there a way not to use aws-sdk ?
@ajaxon I was wondering the same and after some digging, I learned that in order to get a refreshToken along with idToken and accessToken, we have to opt for the authorization code grant flow. We do this by setting response_type=code as a request parameter to the /oauth2/authorize endpoint as mentioned in their docs.
When response_type=token, that uses the implicit flow which does not return a refreshToken for security reasons I think.
With the authorization code grant flow, we get an authorization code sent back as a query string parameter in the redirect url, which we'd then pass with a request to their /oauth2/token endpoint and get a json response back with the refreshToken included.
I got up to this point but get a 405 Method Not Allowed response from the /oauth2/token endpoint and not sure why. 😕
I also struggled with this and managed to make it work for me, at least in minimal level. Finally, I created a simple app with setup instructions (see repo link below). Hope it is helpful for someone.
https://github.com/juhamust/serverless-aws-cognito-login
I just made it using firebase in ~30 mins 😕
For now it's required using the hosted UI in AWS, but what about those that want to have their own UI? not using redirects on external services, seriously why? hope you adapt this in futures release....
About the jwt token from cognito for authenticate to AWS API Gateway? I just made my own authorizer for jwt using the firebase implementation and gets all working in my way...
Can someone from AWS confirm whether it is possible or not to use the new "Federation" approach without the need to use the hosted UI?
@djar I have figured out that if an app client only has a single identity provider then it will default to that provider and skip the hosted UI. So what I have done is made a Facebook client and a Google Client. Then the Facebook and Google login buttons on my site run use case 1 with the respective client ids. It seems like a work around, but gets the job done.
Hi sam @sam-jg, I tried the same you say, however it still shows the hosted UI but only showing facebook in my case, did you do something else to avoid the hosted UI and get logged in? Thanks in advance
It would be good of AWS to provide a response or information on this rather than letting the community guess and flounder.
@ed-zm what 'Allowed OAuth Flows' are you using? I only have 'Implicit grant' selected.