Collecting context data for Amazon Cognito advanced security feature adaptive authentication
This post shows how to collect context data for Amazon Cognito advanced security feature adaptive authentication
Vishal Jakharia
Amazon Employee
Published Nov 20, 2024
Amazon Cognito advanced security features offers adaptive authentication, which allows you to configure your user pool to block suspicious sign-ins or add second factor authentication in response to an increased risk level. For each sign-in attempt, Amazon Cognito generates a risk score for how likely the sign-in request is to be from a compromised source.
The risk score is calculated based on multiple factors collected from the end-user device and derived from the properties of the request. Some factors that contribute to the risk evaluation by Amazon Cognito are IP address, user agent and geographical distance from other sign-in attempts. In order for Amazon Cognito to evaluate accurate risk score it is essential to pass context data to Cognito.
The context data consists of two parts: an end user IP address and EncodedData. The IP address can be added directly in the context data, but the hard part of context data is getting the EncodedData parameter that includes the end-user device metadata which is important for advanced security features evaluation of the risk.
Developers can integrate their application with Amazon Cognito by using the managed login pages (Hosted UI) or Cognito APIs in AWS Amplify and AWS SDKs. The purpose of this document is to provide guidelines on how to collect context data from applications on the end user's device when using any of the above methods to integrate the application with Amazon Cognito.
Context data is collected differently for the client-side (InitiateAuth, RespondToAuthChallenge) and server-side (AdminInitiateAuth, AdminRespondToAuthChallenge) API operations for authentication. Client-side operations take a UserContextData object and are intended to be used from an end-user’s device. Server-side operations take a ContextData object and are intended to be used from a proxy server. The parameters that these objects have in common, IPAddress and EncodedData, is the set of client properties that the data-collection functions gather. For both client-side and server-side APIs, IP and EncodedData should be collected from the end-user’s device.
Depending upon method you are using to integrate application with Cognito, there are two approaches to send context data to the Amazon Cognito service.
- Collecting UserContextData for client-side Cognito APIs - Collect UserContextData on the end user’s device, and include it as a parameter on Cognito API calls from the end-user’s device.
- Collecting ContextData for server-side Cognito APIs - Collect ContextData on the end user’s device, forward it to your proxy server, and include it as a parameter on Cognito API calls from your proxy server.
If you have integrated your application using any of the below Amplify libraries, then refer to their respective integration in order to collect UserContextData.
- Setup a new amplify project/app in your preferred framework/language, for example Android: https://docs.amplify.aws/gen1/android/tools/libraries/
- Add the Amplify Auth client package to your Android Amplify app. Follow the instructions in the following document for setting up Amplify Auth in your app:
Note: With the Amplify CLI setup for Cognito (
amplify add auth
), the manual configuration does not give you the option to enable advanced security features. 3.The user pool APIs invoked in the auth client package collect and add UserContextData to the request out of the box. Refer to the sample code at Github. There is no additional configuration required to collect UserContextData for Amplify apps with Android.
- Setup a new Amplify project/app in your preferred framework or language, for example Flutter: https://docs.amplify.aws/gen1/flutter/build-a-backend/auth/set-up-auth/
- If you are using the gen1 documentation then add Amplify auth to your app by following the instructions in the following document: https://docs.amplify.aws/gen1/flutter/build-a-backend/auth/set-up-auth/
- If you are using the quick-start guide for gen2, the quick-start template sets up the Amplify auth library for you. The auth capabilities in gen2 use TypeScript and the AWS CDK instead of the Amplify CLI.
- The user pool APIs invoked in the auth client package collect and add UserContextData to the request out of the box. Refer to the sample code at Github. There is no additional configuration required to collect UserContextData for Flutter apps with Amplify.
If you are incorporating the Amplify auth library with React, Vue or NextJS app, add amazon-cognito-advanced-security-data.min.js to your application to collect UserContextData.
- Setup a new Amplify project/app in your preferred framework or language, for example React: https://docs.amplify.aws/gen1/react/build-a-backend/auth/set-up-auth/
- If you are using gen1 documentation then add Amplify auth to your app by following the instructions in the following document: https://docs.amplify.aws/gen1/react/build-a-backend/auth/set-up-auth/
- If you are using the quick-start guide for gen2, the quick-start template sets up the Amplify auth library for you. The auth capabilities in gen2 use TypeScript and the AWS CDK instead of the Amplify CLI.
- The user pool APIs in the auth client package for React and other JavaScript-based applications don’t add UserContextData to the request by default. To compensate for this limitation, import the amazon-cognito-advanced-security-data.min.js script into the application with the UseEffect hook as demonstrated in the following example. Replace <region> with an AWS Region from the following list: us-east-1, us-east-2, us-west-2, eu-west-1, eu-west-2, or eu-central-1.
A Vue application contains index.html in the root directory of the project. To populate UserContextData, you can add amazon-cognito-advanced-security-data.min.js to index.html as demonstrated in the following example.
Replace <region> with an AWS Region from the following list: us-east-1, us-east-2, us-west-2, eu-west-1, eu-west-2, or eu-central-1.
Replace <region> with an AWS Region from the following list: us-east-1, us-east-2, us-west-2, eu-west-1, eu-west-2, or eu-central-1.
To collect UserContextData for a NextJS application, import
next/script
and then use the Script component in the root directory of your application, as demonstrated in the following example.Replace <region> with an AWS Region from the following list: us-east-1, us-east-2, us-west-2, eu-west-1, eu-west-2, or eu-central-1.The user pool managed login pages (Hosted UI) capture UserContextData like the IP address and device information without additional configuration. The managed login pages have user sign-in, sign-up and forgot-password operations in users’ browsers. When advanced security features are active, threat protection logs user activity with full context data automatically.
Client-side user pool API operations like InitiateAuth and RespondToAuthChallenge accept UserContextData for risk evaluation. The following is the expected format for the UserContextData object that your application can pass to unauthenticated API operations for risk evaluation.
- You can directly pass the end user device’s IP address, as it is used for IP propagation. Amazon Cognito allows application developers to propagate IP address as part of the caller context data in unauthenticated calls to Amazon Cognito. When Amazon Cognito’s advanced security features (ASF) are enabled, this feature improves risk calculation and resulting authentication decisions performed in flows such as sign-up, account confirmation and password change.User pools don’t accept the IP address in UserContextData by default. To pass IP addresses, set the EnablePropagateAdditionalUserContextData parameter to true when you create or update an app client in your user pool. You can only activate EnablePropagateAdditionalUserContextData in an app client that has a client secret.
- Amazon Cognito components in AWS SDKs are libraries that connect and interact with the service. You can generate EncodedData when making user pool API requests with SDKs.If your application is using JavaScript, iOS or Android SDKs to interact with user pools, refer to the following procedure to collect encoded context data for advanced security.
The amazon-cognito-advanced-security-data.min.js module collects EncodedData that you can pass to Amazon Cognito.
Add the amazon-cognito-advanced-security-data.min.js module to your JavaScript configuration. Replace <region> with an AWS Region from the following list: us-east-1, us-east-2, us-west-2, eu-west-1, eu-west-2, or eu-central-1.
Add the amazon-cognito-advanced-security-data.min.js module to your JavaScript configuration. Replace <region> with an AWS Region from the following list: us-east-1, us-east-2, us-west-2, eu-west-1, eu-west-2, or eu-central-1.
To generate an encodedContextData object that you can use in the EncodedData parameter, add the following to your JavaScript application source:
The following example code demonstrates how to invoke the script and add UserContextData to user pool InitiateAuth API requests in the JavaScript SDK
To generate context data, iOS applications can integrate the Mobile SDK for iOS module AWSCognitoIdentityProviderASF.
To collect encoded context data for advanced security, add the following snippet to your application:
To collect encoded context data for advanced security, add the following snippet to your application:
To generate context data, Android applications can integrate the Mobile SDK for Android module aws-android-sdk-cognitoidentityprovider-asf.
To collect encoded context data for advanced security, add the following snippet to your application:
To collect encoded context data for advanced security, add the following snippet to your application:
For more information, see Collecting UserContextData when using SDK.
Cognito authenticated APIs like AdminInitiateAuth and AdminRespondToAuthChallenge accept ContextData for threat protection risk evaluation.
In this case, collect EncodedData from the end-user device and pass it to the application server or proxy server which add those context data to authenticated API operations like AdminInitiateAuth and AdminRespondToAuthChallenge as shown in above figure.
Here is example of sample ContextData that needs to be collected when calling Cognito authenticated APIs for risk evaluation. IpAddress should be the end user device IP. In most cases this can be derived from the headers of the request to the proxy server; however, this can also be populated using custom logic as well.
In above example, the IP address should be the end-user device IP, and EncodedData needs to be collected as explained above. You can use one of the methods from the above section depending upon type of integration to generate EncodedData on the end-user device and pass it to your proxy server.
For more information, see Context data libraries for client-server applications.
To protect against account takeover collecting ContextData from the end user's device and passing it to Cognito is important for accurate risk evaluation when using advanced security features. Adaptive authentication in Amazon Cognito advanced security features takes actions to secure user accounts for detected risks, and enhances the security posture of your application. Feel free to share your feedback on community.aws!
Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.