Page updated Feb 28, 2024

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.

1import { Auth } from 'aws-amplify';
2
3// To derive necessary data from the provider
4const {
5 token, // the token you get from the provider
6 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'
7 expiresIn, // the time in ms which describes how long the token could live
8 user, // the user object you defined, e.g. { username, email, phone_number }
9 identity_id // Optional, the identity id specified by the provider
10} = getFromProvider(); // arbitrary function
11
12async function getCognitoCredentials() {
13 try {
14 const cred = await Auth.federatedSignIn(
15 domainOrProviderName,
16 {
17 token,
18 identity_id, // Optional
19 expires_at: expiresIn * 1000 + new Date().getTime() // the expiration timestamp
20 },
21 user
22 );
23 console.log(cred);
24
25 const authenticatedUser = await Auth.currentAuthenticatedUser();
26
27 console.log(authenticatedUser);
28 } catch (err) {
29 console.log(err);
30 }
31}

Note that this isn't from a Cognito User Pool so the user you get after calling this method is not a Cognito User.

Facebook sign-in (React)

1import React, { useEffect } from 'react';
2import { Auth } from 'aws-amplify';
3// To federated sign in from Facebook
4const SignInWithFacebook = () => {
5 useEffect(() => {
6 if (!window.FB) createScript();
7 }, []);
8
9 const signIn = () => {
10 const fb = window.FB;
11 fb.getLoginStatus((response) => {
12 if (response.status === 'connected') {
13 getAWSCredentials(response.authResponse);
14 } else {
15 fb.login(
16 (response) => {
17 if (!response || !response.authResponse) {
18 return;
19 }
20 getAWSCredentials(response.authResponse);
21 },
22 {
23 // the authorized scopes
24 scope: 'public_profile,email'
25 }
26 );
27 }
28 });
29 };
30
31 const getAWSCredentials = (response) => {
32 const { accessToken, expiresIn } = response;
33 const date = new Date();
34 const expires_at = expiresIn * 1000 + date.getTime();
35 if (!accessToken) {
36 return;
37 }
38
39 const fb = window.FB;
40 fb.api('/me', { fields: 'name,email' }, (response) => {
41 const user = {
42 name: response.name,
43 email: response.email
44 };
45
46 getCognitoCredentials(
47 'facebook',
48 { token: accessToken, expires_at },
49 user
50 );
51 });
52 };
53
54 const getCognitoCredentials = async (providerName, federateOptions, user) => {
55 try {
56 const credentials = await Auth.federatedSignIn(
57 providerName,
58 federateOptions,
59 user
60 );
61 console.log(credentials);
62 } catch (err) {
63 console.log(err);
64 }
65 };
66
67 const createScript = () => {
68 // load the sdk
69 window.fbAsyncInit = fbAsyncInit;
70 const script = document.createElement('script');
71 script.src = 'https://connect.facebook.net/en_US/sdk.js';
72 script.async = true;
73 script.onload = initFB;
74 document.body.appendChild(script);
75 };
76
77 const initFB = () => {
78 const fb = window.FB;
79 console.log('FB SDK initialized');
80 };
81
82 const fbAsyncInit = () => {
83 // init the fb sdk client
84 const fb = window.FB;
85 fb.init({
86 appId: 'your_facebook_app_id',
87 cookie: true,
88 xfbml: true,
89 version: 'v2.11'
90 });
91 };
92
93 return (
94 <div>
95 <button onClick={signIn}>Sign in with Facebook</button>
96 </div>
97 );
98};

Facebook Sign-in (React Native - Expo)

1import Expo from 'expo';
2import React from 'react';
3import { Amplify, Auth } from 'aws-amplify';
4
5const App = () => {
6 const signIn = async () => {
7 const { type, token, expires } =
8 await Expo.Facebook.logInWithReadPermissionsAsync(
9 'YOUR_FACEBOOK_APP_ID',
10 {
11 permissions: ['public_profile']
12 }
13 );
14 if (type === 'success') {
15 // sign in with federated identity
16 try {
17 const credentials = await Auth.federatedSignIn(
18 'facebook',
19 { token, expires_at: expires },
20 { name: 'USER_NAME' }
21 );
22 console.log('get aws credentials', credentials);
23 } catch (err) {
24 console.log(err);
25 }
26 }
27 };
28
29 // ...
30
31 return (
32 <View style={styles.container}>
33 <Button title="FBSignIn" onPress={signIn} />
34 </View>
35 );
36};

Google sign-in (React)

1import React, { useEffect } from 'react';
2import jwt from 'jwt-decode';
3import { Auth } from 'aws-amplify';
4
5const SignInWithGoogle = () => {
6 useEffect(() => {
7 // Check for an existing Google client initialization
8 if (!window.google?.accounts) createScript();
9 }, []);
10
11 // Load the Google client
12 const createScript = () => {
13 const script = document.createElement('script');
14 script.src = 'https://accounts.google.com/gsi/client';
15 script.async = true;
16 script.defer = true;
17 script.onload = initGsi;
18 document.body.appendChild(script);
19 }
20
21 // Initialize Google client and render Google button
22 const initGsi = () => {
23 if (window.google?.accounts) {
24 window.google.accounts.id.initialize({
25 client_id: process.env.GOOGLE_CLIENT_ID,
26 callback: (response: any) => {
27 getAWSCredentials(response.credential)
28 },
29 });
30 window.google.accounts.id.renderButton(
31 document.getElementById("googleSignInButton"),
32 { theme: "outline", size: "large" }
33 );
34 }
35 }
36
37 // Exchange Google token for temporary AWS credentials
38 const getAWSCredentials = async (credential: string) => {
39 const token = jwt(credential) as any;
40 const user = {
41 email: token.email,
42 name: token.name
43 };
44 await Auth.federatedSignIn(
45 'google',
46 { token: credential, expires_at: token.exp },
47 user
48 );
49 }
50
51 return (
52 <div>
53 <button id="googleSignInButton"/>
54 </div>
55 );
56}
1import React, { useEffect } from 'react';
2import jwt from 'jwt-decode';
3import { Auth } from 'aws-amplify';
4
5const SignInWithGoogle = () => {
6 useEffect(() => {
7 // Check for an existing Google client initialization
8 if (!window.google?.accounts) createScript();
9 }, []);
10
11 // Load the Google client
12 const createScript = () => {
13 const script = document.createElement('script');
14 script.src = 'https://accounts.google.com/gsi/client';
15 script.async = true;
16 script.defer = true;
17 script.onload = initGsi;
18 document.body.appendChild(script);
19 }
20
21 // Initialize Google client and render Google button
22 const initGsi = () => {
23 if (window.google?.accounts) {
24 window.google.accounts.id.initialize({
25 client_id: process.env.GOOGLE_CLIENT_ID,
26 callback: (response: any) => {
27 getAWSCredentials(response.credential)
28 },
29 });
30 window.google.accounts.id.renderButton(
31 document.getElementById("googleSignInButton"),
32 { theme: "outline", size: "large" }
33 );
34 }
35 }
36
37 // Exchange Google token for temporary AWS credentials
38 const getAWSCredentials = async (credential) => {
39 const token = jwt(credential);
40 const user = {
41 email: token.email,
42 name: token.name
43 };
44 await Auth.federatedSignIn(
45 'google',
46 { token: credential, expires_at: token.exp },
47 user
48 );
49 }
50
51 return (
52 <div>
53 <button id="googleSignInButton"/>
54 </div>
55 );
56}

Retrieve JWT Tokens

After the federated login, you can retrieve related JWT tokens from the local cache using the Cache module:

Browser sample

1import { Cache } from 'aws-amplify';
2
3// Run this after the sign-in
4const federatedInfo = Cache.getItem('federatedInfo');
5const { token } = federatedInfo;

React Native sample

1import { Cache } from 'aws-amplify';
2
3// inside an async function
4// Run this after the sign-in
5const federatedInfo = await Cache.getItem('federatedInfo');
6const { 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:

Note: Automatic token refresh for Google and Facebook is not supported in React Native. Automatic token refresh is supported when used with Cognito User pool.

JWT Token Refresh sample

1import { Auth } from 'aws-amplify';
2
3async function refreshToken() {
4 // refresh the token here and get the new token info
5 // ......
6
7 const data = {
8 token, // the token from the provider
9 expires_at, // the timestamp for the expiration
10 identity_id // optional, the identityId for the credentials
11 };
12
13 return data;
14}
15
16Auth.configure({
17 refreshHandlers: {
18 developer: refreshToken // the property could be 'google', 'facebook', 'amazon', 'developer', OpenId domain
19 }
20});

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:

1const { idToken, domain, name, email, phoneNumber } = getFromAuth0(); // get the user credentials and info from auth0
2const { exp } = decodeJWTToken(idToken); // Please decode the id token in order to get the expiration time
3
4async function getCognitoCredentials() {
5 try {
6 const cred = await Auth.federatedSignIn(
7 domain, // The Auth0 Domain,
8 {
9 token: idToken, // The id token from Auth0
10 // expires_at means the timestamp when the token provided expires,
11 // here you can derive it from the expiresIn parameter provided,
12 // then convert its unit from second to millisecond, and add the current timestamp
13 expires_at: exp * 1000 // the expiration timestamp
14 },
15 {
16 // the user object, you can put whatever property you get from the Auth0
17 // for example:
18 name, // the user name
19 email, // Optional, the email address
20 phoneNumber // Optional, the phone number
21 }
22 );
23
24 console.log(cred);
25 } catch (err) {
26 console.log(err);
27 }
28}

Step 3. Get the current user and current Credentials:

1const user = await Auth.currentAuthenticatedUser();
2console.log(user);
3const creds = await Auth.currentCredentials();
4console.log(creds);
5// 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:

1async function refreshToken() {
2 // refresh the token here and get the new token info
3 // ......
4
5 const data = {
6 token, // the token from the provider
7 expires_at, // the timestamp when the token expires (in milliseconds)
8 identity_id // optional, the identityId for the credentials
9 };
10
11 return data;
12}
13
14Auth.configure({
15 refreshHandlers: {
16 your_auth0_domain: refreshToken
17 }
18});

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.

1import { Auth } from 'aws-amplify';
2
3async function signIn() {
4 try {
5 const user = await Auth.signIn({
6 username, // Required, the username
7 password, // Optional, the password
8 validationData // Optional, an object of key-value pairs which can contain any key and will be passed to your Lambda trigger as-is.
9 });
10 console.log(user);
11 } catch (err) {
12 console.log(err);
13 }
14}

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.

1Auth.signUp({
2 username,
3 password,
4 attributes: {
5 email, // optional
6 phone_number // optional - E.164 number convention
7 // other custom attributes
8 },
9 autoSignIn: {
10 // optional - enables auto sign in after user is confirmed
11 enabled: true,
12 validationData // optional
13 }
14});

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 of autoSignIn 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:

1import { Auth } from 'aws-amplify';
2import Route53 from 'aws-sdk/clients/route53';
3
4async function changeResourceRecordSets() {
5 try {
6 const credentials = await Auth.currentCredentials();
7
8 const route53 = new Route53({
9 apiVersion: '2013-04-01',
10 credentials: Auth.essentialCredentials(credentials)
11 });
12
13 // more code working with route53 object
14 //route53.changeResourceRecordSets();
15 } catch (err) {
16 console.log(err);
17 }
18}

Full API Documentation for Service Interface Objects is available here.

Note: To work with Service Interface Objects, your Amazon Cognito users' IAM role must have the appropriate permissions to call the requested services.