Page updated Jan 16, 2024

Advanced workflows

Subscribing to Events

You can take specific actions when users sign-in or sign-out by subscribing to authentication events in your app. Please see our Hub Module Developer Guide for more information.

Identity Pool Federation

You can alternatively create your own custom credentials provider to get AWS credentials directly from Cognito Federated Identities and not use User Pool federation. You must supply the custom credentials provider to Amplify via the Amplify.configure method call. Below, you can see sample code of how such a custom provider can be built to achieve the use case.

1import { Amplify } from 'aws-amplify';
2import {
3 fetchAuthSession,
4 CredentialsAndIdentityIdProvider,
5 CredentialsAndIdentityId,
6 GetCredentialsOptions,
7 AuthTokens,
8} from 'aws-amplify/auth';
9
10// Note: This example requires installing `@aws-sdk/client-cognito-identity` to obtain Cognito credentials
11// npm i @aws-sdk/client-cognito-identity
12import { CognitoIdentity } from '@aws-sdk/client-cognito-identity';
13
14// You can make use of the sdk to get identityId and credentials
15const cognitoidentity = new CognitoIdentity({
16 region: '<region-from-config>',
17});
18
19// Note: The custom provider class must implement CredentialsAndIdentityIdProvider
20class CustomCredentialsProvider implements CredentialsAndIdentityIdProvider {
21
22 // Example class member that holds the login information
23 federatedLogin?: {
24 domain: string,
25 token: string
26 };
27
28 // Custom method to load the federated login information
29 loadFederatedLogin(login?: typeof this.federatedLogin) {
30 // You may also persist this by caching if needed
31 this.federatedLogin = login;
32 }
33
34 async getCredentialsAndIdentityId(
35 getCredentialsOptions: GetCredentialsOptions
36 ): Promise<CredentialsAndIdentityId | undefined> {
37 try {
38
39 // You can add in some validation to check if the token is available before proceeding
40 // You can also refresh the token if it's expired before proceeding
41
42 const getIdResult = await cognitoidentity.getId({
43 // Get the identityPoolId from config
44 IdentityPoolId: '<identity-pool-id-from-config>',
45 Logins: { [this.federatedLogin.domain]: this.federatedLogin.token },
46 });
47
48 const cognitoCredentialsResult = await cognitoidentity.getCredentialsForIdentity({
49 IdentityId: getIdResult.IdentityId,
50 Logins: { [this.federatedLogin.domain]: this.federatedLogin.token },
51 });
52
53 const credentials: CredentialsAndIdentityId = {
54 credentials: {
55 accessKeyId: cognitoCredentialsResult.Credentials?.AccessKeyId,
56 secretAccessKey: cognitoCredentialsResult.Credentials?.SecretKey,
57 sessionToken: cognitoCredentialsResult.Credentials?.SessionToken,
58 expiration: cognitoCredentialsResult.Credentials?.Expiration,
59 },
60 identityId: getIdResult.IdentityId,
61 };
62 return credentials;
63 } catch (e) {
64 console.log('Error getting credentials: ', e);
65 }
66 }
67 // Implement this to clear any cached credentials and identityId. This can be called when signing out of the federation service.
68 clearCredentialsAndIdentityId(): void {}
69}
70
71// Create an instance of your custom provider
72const customCredentialsProvider = new CustomCredentialsProvider();
73Amplify.configure(awsconfig, {
74 Auth: {
75 // Supply the custom credentials provider to Amplify
76 credentialsProvider: customCredentialsProvider
77 },
78});

Now that the custom credentials provider is built and supplied to Amplify.configure, let's look at how you can use the custom credentials provider to finish federation into Cognito identity pool.

Facebook sign-in (React)

1import React, { useEffect } from 'react';
2import {
3 fetchAuthSession,
4} from 'aws-amplify/auth';
5
6// To federated sign in from Facebook
7const SignInWithFacebook = () => {
8
9 useEffect(() => {
10 if (!window.FB) createScript();
11 }, [])
12
13 const signIn = () => {
14 const fb = window.FB;
15 fb.getLoginStatus(response => {
16 if (response.status === 'connected') {
17 getAWSCredentials(response.authResponse);
18 } else {
19 fb.login(
20 response => {
21 if (!response || !response.authResponse) {
22 return;
23 }
24 customCredentialsProvider.loadFederatedLogin({
25 domain: 'graph.facebook.com',
26 token: response.authResponse.accessToken,
27 });
28 const fetchSessionResult = await fetchAuthSession(); // will return the credentials
29 console.log('fetchSessionResult: ', fetchSessionResult);
30 },
31 {
32 // the authorized scopes
33 scope: 'public_profile,email'
34 }
35 );
36 }
37 });
38 }
39
40 const createScript = () => {
41 // load the sdk
42 window.fbAsyncInit = fbAsyncInit;
43 const script = document.createElement('script');
44 script.src = 'https://connect.facebook.net/en_US/sdk.js';
45 script.async = true;
46 script.onload = initFB;
47 document.body.appendChild(script);
48 }
49
50 const initFB = () => {
51 const fb = window.FB;
52 console.log('FB SDK initialized');
53 }
54
55 const fbAsyncInit = () => {
56 // init the fb sdk client
57 const fb = window.FB;
58 fb.init({
59 appId : 'your_facebook_app_id',
60 cookie : true,
61 xfbml : true,
62 version : 'v2.11'
63 });
64 }
65
66 return (
67 <div>
68 <button onClick={signIn}>Sign in with Facebook</button>
69 </div>
70 );
71}

Google sign-in (React)

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

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 custom credentials provider you created at the start:

1import { fetchAuthSession } from 'aws-amplify/auth';
2
3const { idToken, domain, name, email, phoneNumber } = getFromAuth0(); // get the user credentials and info from auth0
4
5async function getCognitoCredentials() {
6 try {
7 customCredentialsProvider.loadFederatedLogin({
8 domain,
9 token: idToken
10 });
11 const fetchSessionResult = await fetchAuthSession(); // will return the credentials
12 console.log('fetchSessionResult: ', fetchSessionResult);
13 } catch (err) {
14 console.log(err);
15 }
16}

Lambda Triggers

The CLI allows you to configure Lambda Triggers for your 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 Authentication Lambda trigger enabled, you can pass clientMetadata as an option for signIn. This metadata can be used to implement additional validations around authentication.

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

Passing metadata to other Lambda triggers

Many Cognito Lambda Triggers also accept unsanitized key/value pairs in the form of a clientMetadata attribute. This attribute can be specified for various Auth APIs which result in Cognito Lambda Trigger execution.

These APIs include:

  • signIn
  • signUp
  • confirmSignIn
  • confirmSignUp
  • resetPassword
  • confirmResetPassword
  • resendSignUpCode
  • updateUserAttributes

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 with AWS Services in authenticated State. You can call methods on any AWS Service interface object by passing your credentials from Amplify fetchAuthSession to the service call constructor:

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

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

Custom Token providers

Create a custom Auth token provider for situations where you would like provide your own tokens for a service. For example, using OIDC Auth with AppSync. You must supply the token provider to Amplify via the Amplify.configure method call. Below, you can see sample code of how such a custom provider can be built to achieve the use case.

1import { Amplify } from 'aws-amplify';
2import { TokenProvider, decodeJWT } from 'aws-amplify/auth';
3
4// ...
5
6const myTokenProvider: TokenProvider = {
7 async getTokens({ forceRefresh } = {}) {
8 if (forceRefresh) {
9 // try to obtain new tokens if possible
10 }
11
12 const accessTokenString = '<insert JWT from provider>';
13 const idTokenString = '<insert JWT from provider>';
14
15 return {
16 accessToken: decodeJWT(accessTokenString),
17 idToken: decodeJWT(idTokenString),
18 };
19 },
20};
21
22Amplify.configure(awsconfig, {
23 Auth: {
24 tokenProvider: myTokenProvider
25 }
26});

API reference

For the complete API documentation for Authentication module, visit our API Reference