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.
import { Amplify } from 'aws-amplify';import { fetchAuthSession, CredentialsAndIdentityIdProvider, CredentialsAndIdentityId, GetCredentialsOptions, AuthTokens,} from 'aws-amplify/auth';
// Note: This example requires installing `@aws-sdk/client-cognito-identity` to obtain Cognito credentials// npm i @aws-sdk/client-cognito-identityimport { CognitoIdentity } from '@aws-sdk/client-cognito-identity';
// You can make use of the sdk to get identityId and credentialsconst cognitoidentity = new CognitoIdentity({ region: '<region-from-config>',});
// Note: The custom provider class must implement CredentialsAndIdentityIdProviderclass CustomCredentialsProvider implements CredentialsAndIdentityIdProvider {
// Example class member that holds the login information federatedLogin?: { domain: string, token: string };
// Custom method to load the federated login information loadFederatedLogin(login?: typeof this.federatedLogin) { // You may also persist this by caching if needed this.federatedLogin = login; }
async getCredentialsAndIdentityId( getCredentialsOptions: GetCredentialsOptions ): Promise<CredentialsAndIdentityId | undefined> { try {
// You can add in some validation to check if the token is available before proceeding // You can also refresh the token if it's expired before proceeding
const getIdResult = await cognitoidentity.getId({ // Get the identityPoolId from config IdentityPoolId: '<identity-pool-id-from-config>', Logins: { [this.federatedLogin.domain]: this.federatedLogin.token }, });
const cognitoCredentialsResult = await cognitoidentity.getCredentialsForIdentity({ IdentityId: getIdResult.IdentityId, Logins: { [this.federatedLogin.domain]: this.federatedLogin.token }, });
const credentials: CredentialsAndIdentityId = { credentials: { accessKeyId: cognitoCredentialsResult.Credentials?.AccessKeyId, secretAccessKey: cognitoCredentialsResult.Credentials?.SecretKey, sessionToken: cognitoCredentialsResult.Credentials?.SessionToken, expiration: cognitoCredentialsResult.Credentials?.Expiration, }, identityId: getIdResult.IdentityId, }; return credentials; } catch (e) { console.log('Error getting credentials: ', e); } } // Implement this to clear any cached credentials and identityId. This can be called when signing out of the federation service. clearCredentialsAndIdentityId(): void {}}
// Create an instance of your custom providerconst customCredentialsProvider = new CustomCredentialsProvider();Amplify.configure(awsconfig, { Auth: { // Supply the custom credentials provider to Amplify credentialsProvider: customCredentialsProvider },});
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 Native - Expo)
import Expo from 'expo';import React from 'react';import { fetchAuthSession } from 'aws-amplify/auth';
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 { customCredentialsProvider.loadFederatedLogin({ domain: 'graph.facebook.com', token: token }); const fetchSessionResult = await fetchAuthSession(); // will return the credentials console.log('fetchSessionResult: ', fetchSessionResult); } catch (err) { console.log(err); } } };
// ...
return ( <View style={styles.container}> <Button title="FBSignIn" onPress={signIn} /> </View> );};
Lambda Triggers
With the triggers property of defineAuth and defineFunction from the new Functions implementation, you can define Lambda Triggers for your Cognito User Pool. These enable you to add custom functionality to your registration and authentication flows. Check out a preSignUp hook example here.
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.
import { signIn } from 'aws-amplify/auth';
async function handleSignIn(username: string, password: string) { try { await signIn({ username, password, options: { clientMetadata: {} // Optional, an object of key-value pairs which can contain any key and will be passed to your Lambda trigger as-is. } }); } catch (err) { console.log(err); }}
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:
import { fetchAuthSession } from 'aws-amplify/auth';import Route53 from 'aws-sdk/clients/route53';
async function changeResourceRecordSets() { try { const { credentials } = await fetchAuthSession();
const route53 = new Route53({ apiVersion: '2013-04-01', credentials });
// more code working with route53 object //route53.changeResourceRecordSets(); } catch (err) { console.log(err); }}
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.
import { Amplify } from 'aws-amplify';import { TokenProvider, decodeJWT } from 'aws-amplify/auth';
// ...
const myTokenProvider: TokenProvider = { async getTokens({ forceRefresh } = {}) { if (forceRefresh) { // try to obtain new tokens if possible }
const accessTokenString = '<insert JWT from provider>'; const idTokenString = '<insert JWT from provider>'; return { accessToken: decodeJWT(accessTokenString), idToken: decodeJWT(idTokenString), }; },};
Amplify.configure(awsconfig, { Auth: { tokenProvider: myTokenProvider }});
API reference
For the complete API documentation for Authentication module, visit our API Reference