Advanced workflows
Subscribing Events
You can take specific actions when users sign-in or sign-out by subscribing authentication events in your app. Please see our Hub Module Developer Guide for more information.
Identity Pool Federation
You can alternatively use Auth.federatedSignIn()
to get AWS credentials directly from Cognito Federated Identities and not use User Pool federation. If you have logged in with Auth.signIn()
you can not call Auth.federatedSignIn()
as Amplify will perform this federation automatically for you in the background.
In general, if you are using Cognito User Pools to manage user Sign-Up and Sign-In, you should only call Auth.federatedSignIn()
when using OAuth flows or the Hosted UI.
import { Auth } from 'aws-amplify';
// To derive necessary data from the providerconst { token, // the token you get from the provider domainOrProviderName, // Either the domain of the provider(e.g. accounts.your-openid-provider.com) or the provider name, for now the library only supports 'google', 'facebook', 'amazon', 'developer' expiresIn, // the time in ms which describes how long the token could live user, // the user object you defined, e.g. { username, email, phone_number } identity_id // Optional, the identity id specified by the provider} = getFromProvider(); // arbitrary function
async function getCognitoCredentials() { try { const cred = await Auth.federatedSignIn( domainOrProviderName, { token, identity_id, // Optional expires_at: expiresIn * 1000 + new Date().getTime() // the expiration timestamp }, user ); console.log(cred);
const authenticatedUser = await Auth.currentAuthenticatedUser();
console.log(authenticatedUser); } catch (err) { console.log(err); }}
Facebook sign-in (React)
import React, { useEffect } from 'react';import { Auth } from 'aws-amplify';// To federated sign in from Facebookconst SignInWithFacebook = () => { useEffect(() => { if (!window.FB) createScript(); }, []);
const signIn = () => { const fb = window.FB; fb.getLoginStatus((response) => { if (response.status === 'connected') { getAWSCredentials(response.authResponse); } else { fb.login( (response) => { if (!response || !response.authResponse) { return; } getAWSCredentials(response.authResponse); }, { // the authorized scopes scope: 'public_profile,email' } ); } }); };
const getAWSCredentials = (response) => { const { accessToken, expiresIn } = response; const date = new Date(); const expires_at = expiresIn * 1000 + date.getTime(); if (!accessToken) { return; }
const fb = window.FB; fb.api('/me', { fields: 'name,email' }, (response) => { const user = { name: response.name, email: response.email };
getCognitoCredentials( 'facebook', { token: accessToken, expires_at }, user ); }); };
const getCognitoCredentials = async (providerName, federateOptions, user) => { try { const credentials = await Auth.federatedSignIn( providerName, federateOptions, user ); console.log(credentials); } catch (err) { console.log(err); } };
const createScript = () => { // load the sdk window.fbAsyncInit = fbAsyncInit; const script = document.createElement('script'); script.src = 'https://connect.facebook.net/en_US/sdk.js'; script.async = true; script.onload = initFB; document.body.appendChild(script); };
const initFB = () => { const fb = window.FB; console.log('FB SDK initialized'); };
const fbAsyncInit = () => { // init the fb sdk client const fb = window.FB; fb.init({ appId: 'your_facebook_app_id', cookie: true, xfbml: true, version: 'v2.11' }); };
return ( <div> <button onClick={signIn}>Sign in with Facebook</button> </div> );};
Facebook Sign-in (React Native - Expo)
import Expo from 'expo';import React from 'react';import { Amplify, Auth } from 'aws-amplify';
const App = () => { const signIn = async () => { const { type, token, expires } = await Expo.Facebook.logInWithReadPermissionsAsync( 'YOUR_FACEBOOK_APP_ID', { permissions: ['public_profile'] } ); if (type === 'success') { // sign in with federated identity try { const credentials = await Auth.federatedSignIn( 'facebook', { token, expires_at: expires }, { name: 'USER_NAME' } ); console.log('get aws credentials', credentials); } catch (err) { console.log(err); } } };
// ...
return ( <View style={styles.container}> <Button title="FBSignIn" onPress={signIn} /> </View> );};
Google sign-in (React)
import React, { useEffect } from 'react';import jwt from 'jwt-decode';import { Auth } from 'aws-amplify';
const SignInWithGoogle = () => { useEffect(() => { // Check for an existing Google client initialization if (!window.google?.accounts) createScript(); }, []);
// Load the Google client const createScript = () => { const script = document.createElement('script'); script.src = 'https://accounts.google.com/gsi/client'; script.async = true; script.defer = true; script.onload = initGsi; document.body.appendChild(script); }
// Initialize Google client and render Google button const initGsi = () => { if (window.google?.accounts) { window.google.accounts.id.initialize({ client_id: process.env.GOOGLE_CLIENT_ID, callback: (response: any) => { getAWSCredentials(response.credential) }, }); window.google.accounts.id.renderButton( document.getElementById("googleSignInButton"), { theme: "outline", size: "large" } ); } }
// Exchange Google token for temporary AWS credentials const getAWSCredentials = async (credential: string) => { const token = jwt(credential) as any; const user = { email: token.email, name: token.name }; await Auth.federatedSignIn( 'google', { token: credential, expires_at: token.exp }, user ); }
return ( <div> <button id="googleSignInButton"/> </div> );}
import React, { useEffect } from 'react';import jwt from 'jwt-decode';import { Auth } from 'aws-amplify';
const SignInWithGoogle = () => { useEffect(() => { // Check for an existing Google client initialization if (!window.google?.accounts) createScript(); }, []);
// Load the Google client const createScript = () => { const script = document.createElement('script'); script.src = 'https://accounts.google.com/gsi/client'; script.async = true; script.defer = true; script.onload = initGsi; document.body.appendChild(script); }
// Initialize Google client and render Google button const initGsi = () => { if (window.google?.accounts) { window.google.accounts.id.initialize({ client_id: process.env.GOOGLE_CLIENT_ID, callback: (response: any) => { getAWSCredentials(response.credential) }, }); window.google.accounts.id.renderButton( document.getElementById("googleSignInButton"), { theme: "outline", size: "large" } ); } }
// Exchange Google token for temporary AWS credentials const getAWSCredentials = async (credential) => { const token = jwt(credential); const user = { email: token.email, name: token.name }; await Auth.federatedSignIn( 'google', { token: credential, expires_at: token.exp }, user ); }
return ( <div> <button id="googleSignInButton"/> </div> );}
Retrieve JWT Tokens
After the federated login, you can retrieve related JWT tokens from the local cache using the Cache module:
Browser sample
import { Cache } from 'aws-amplify';
// Run this after the sign-inconst federatedInfo = Cache.getItem('federatedInfo');const { token } = federatedInfo;
React Native sample
import { Cache } from 'aws-amplify';
// inside an async function// Run this after the sign-inconst federatedInfo = await Cache.getItem('federatedInfo');const { token } = federatedInfo;
Token Refresh
By default, Amplify will automatically refresh the tokens for Google and Facebook, so that your AWS credentials will be valid at all times. But if you are using another federated provider, you will need to provide your own token refresh method:
JWT Token Refresh sample
import { Auth } from 'aws-amplify';
async function refreshToken() { // refresh the token here and get the new token info // ......
const data = { token, // the token from the provider expires_at, // the timestamp for the expiration identity_id // optional, the identityId for the credentials };
return data;}
Auth.configure({ refreshHandlers: { developer: refreshToken // the property could be 'google', 'facebook', 'amazon', 'developer', OpenId domain }});
Federate with Auth0
You can use Auth0
as one of the providers of your Cognito Identity Pool. This will allow users authenticated via Auth0 have access to your AWS resources.
Step 1. Follow Auth0 integration instructions for Cognito Federated Identity Pools
Step 2. Login with Auth0
, then use the id token returned to get AWS credentials from Cognito Federated Identity Pools
using Auth.federatedSignIn
:
const { idToken, domain, name, email, phoneNumber } = getFromAuth0(); // get the user credentials and info from auth0const { exp } = decodeJWTToken(idToken); // Please decode the id token in order to get the expiration time
async function getCognitoCredentials() { try { const cred = await Auth.federatedSignIn( domain, // The Auth0 Domain, { token: idToken, // The id token from Auth0 // expires_at means the timestamp when the token provided expires, // here you can derive it from the expiresIn parameter provided, // then convert its unit from second to millisecond, and add the current timestamp expires_at: exp * 1000 // the expiration timestamp }, { // the user object, you can put whatever property you get from the Auth0 // for example: name, // the user name email, // Optional, the email address phoneNumber // Optional, the phone number } );
console.log(cred); } catch (err) { console.log(err); }}
Step 3. Get the current user and current Credentials:
const user = await Auth.currentAuthenticatedUser();console.log(user);const creds = await Auth.currentCredentials();console.log(creds);// await Auth.currentSession() does not currently support federated identities. Please store the auth0 session info manually(for example, store tokens into the local storage).
Step 4. You can pass a refresh handler to the Auth module to refresh the id token from Auth0
:
async function refreshToken() { // refresh the token here and get the new token info // ......
const data = { token, // the token from the provider expires_at, // the timestamp when the token expires (in milliseconds) identity_id // optional, the identityId for the credentials };
return data;}
Auth.configure({ refreshHandlers: { your_auth0_domain: refreshToken }});
Lambda Triggers
The CLI allows you to configure Lambda Triggers for your AWS Cognito User Pool. These enable you to add custom functionality to your registration and authentication flows. Read more
Pre Authentication and Pre Sign-up Lambda triggers
If you have a Pre Sign-up or Pre Authentication Lambda trigger enabled, you can pass validationData
as one the properties for signUp
or signIn
. This metadata can be used to implement additional validations around authentication, such as restricting the types of user accounts that can be registered.
import { Auth } from 'aws-amplify';
async function signIn() { try { const user = await Auth.signIn({ username, // Required, the username password, // Optional, the password validationData // Optional, an object of key-value pairs which can contain any key and will be passed to your Lambda trigger as-is. }); console.log(user); } catch (err) { console.log(err); }}
Auto Sign-in Lambda triggers
If you have autoSignIn
enabled, you can pass validationData
as property for autoSignIn
parameter. It is used to implement additional validations for authentication. For example, you might choose to allow or disallow user sign-up based on the user's domain. The Lambda trigger receives the validation data and uses it in the validation process.
Auth.signUp({ username, password, attributes: { email, // optional phone_number // optional - E.164 number convention // other custom attributes }, autoSignIn: { // optional - enables auto sign in after user is confirmed enabled: true, validationData // optional }});
Passing metadata to other Lambda triggers
Many Cognito Lambda Triggers also accept unsanitized key/value pairs in the form of a clientMetadata
attribute. To configure a static set of key/value pairs, you can define a clientMetadata
key in the Auth.configure
function. You can also pass a clientMetadata
parameter to the various Auth
functions which result in Cognito Lambda Trigger execution.
These functions include:
Auth.changePassword
Auth.completeNewPassword
Auth.confirmSignIn
Auth.confirmSignUp
Auth.forgotPasswordSubmit
Auth.resendSignUp
Auth.sendCustomChallengeAnswer
Auth.signIn
Auth.signUp
(as a function parameter and part ofautoSignIn
parameter)Auth.updateUserAttributes
Auth.verifyUserAttribute
Please note that some of triggers which accept a validationData
attribute will use clientMetadata
as the value for validationData
. Exercise caution with using clientMetadata
when you are relying on validationData
.
Working with AWS service objects
You can use AWS Service Interface Objects to work AWS Services in authenticated State. You can call methods on any AWS Service interface object by passing your credentials from Auth
object to the service call constructor:
import { Auth } from 'aws-amplify';import Route53 from 'aws-sdk/clients/route53';
async function changeResourceRecordSets() { try { const credentials = await Auth.currentCredentials();
const route53 = new Route53({ apiVersion: '2013-04-01', credentials: Auth.essentialCredentials(credentials) });
// more code working with route53 object //route53.changeResourceRecordSets(); } catch (err) { console.log(err); }}
Full API Documentation for Service Interface Objects is available here.