Authenticating with AWS Amplify, Amazon Cognito, and Azure Entra ID (Azure AD)
Introduction
Amazon Cognito user pools provide support for SAML-based identity providers, enabling seamless integration with enterprise identity systems. In this guide, we’ll walk through the process of setting up authentication using AWS Amplify, Amazon Cognito, and Azure Entra ID.
Overview
The authentication workflow involves integrating Cognito with Azure Entra ID via SAML. The following diagram, from official documentation, visualizes the process.
Cloud Resources
Creating Azure Entra ID
To integrate Azure Entra ID with Amazon Cognito, follow these steps:
1. Navigate to Microsoft Entra ID
Open the Azure portal and navigate to the Microsoft Entra ID
section.
2. Add an Enterprise Application
Select Add > Enterprise application
from the menu.
3. Create a Custom Application
Choose Create your own application
and enter a name such as my-cognito-app
. Select the option Integrate any other application you don't find in the gallery (Non-gallery)
.
4. Configure Single Sign-On (SSO)
Go to the Set up single sign on
section and choose SAML
as the method.
Copy the Metadata URL:
Once the SAML setup page appears, locate and copy the metadata URL. This will be used in the Cognito configuration.
Creating Amazon Cognito User Pool
To integrate Amazon Cognito with Azure Entra ID, you need to create a Cognito user pool. This can be accomplished by defining a CloudFormation template (cognito.yaml
) with the following content:
CloudFormation Template
AWSTemplateFormatVersion: 2010-09-09
Description: Cognito user pool federated with Azure Entra ID
Parameters:
Domain:
Type: String
Description: Cognito user pool domain
CallbackURLs:
Type: CommaDelimitedList
Default: 'http://localhost:3000/'
LogoutURLs:
Type: CommaDelimitedList
Default: 'http://localhost:3000/'
MetadataURL:
Type: String
Description: SAML metadata url of your Azure Entra ID
Resources:
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: cognito-federated-with-azure-entra-id
CognitoUserPoolDomain:
Type: AWS::Cognito::UserPoolDomain
Properties:
Domain: !Ref Domain
UserPoolId: !Ref CognitoUserPool
CognitoUserPoolIdentityProvider:
Type: AWS::Cognito::UserPoolIdentityProvider
Properties:
AttributeMapping:
email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'
name: 'http://schemas.microsoft.com/identity/claims/displayname'
ProviderDetails:
IDPSignout: true
MetadataURL: !Ref MetadataURL
ProviderName: azure-entra-id
ProviderType: SAML
UserPoolId: !Ref CognitoUserPool
CognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
AllowedOAuthFlows:
- code
AllowedOAuthScopes:
- email
- openid
- aws.cognito.signin.user.admin
AllowedOAuthFlowsUserPoolClient: true
CallbackURLs: !Ref CallbackURLs
LogoutURLs: !Ref LogoutURLs
ClientName: public client
SupportedIdentityProviders:
- COGNITO
- !Ref CognitoUserPoolIdentityProvider
UserPoolId: !Ref CognitoUserPool
Keynotes
- Attribute Mapping (Lines 33-35): The URLs for attribute mapping can be found in the metadata URL retrieved from Azure Entra ID.
- OAuth Scope (Line 51): The scope
aws.cognito.signin.user.admin
is required for querying user information from frontend applications using Amplify.
For more details on SAML 2.0 requests and responses supported by Entra ID, refer to the official documentation. Additionally, learn more about Cognito resource servers and scopes in the AWS documentation.
Deploying the CloudFormation Stack
Replace <SAML_METADATA_URL>
with the metadata URL copied earlier and deploy the stack using the following command:
aws cloudformation deploy \
--template-file cognito.yaml \
--stack-name amplify-with-cognito-and-entra-id \
--parameter-overrides Domain=$(uuidgen | tr "[:upper:]" "[:lower:]") MetadataURL='<SAML_METADATA_URL>'
This command deploys the Cognito user pool configured for SAML-based authentication with Azure Entra ID.
Once the deployment is successful, you can proceed with configuring Entra ID’s SAML settings and assigning users to the application.
Updating Entra ID SAML Configuration
To enable Azure Entra ID to work with Amazon Cognito, update the SAML configuration as follows:
1. Retrieve the Cognito Details
Check the User pool ID and the Cognito domain prefix in the Amazon Cognito management console.
2. Edit the SAML Configuration
Open the SAML settings in Azure Entra ID and begin editing.
3. Add Entity ID and Reply URL
Use the following values for the SAML configuration. Refer to the official documentation for more details.
Key | Value |
---|---|
Entity ID | urn:amazon:cognito:sp:<your user pool ID> |
Reply URL | https://<yourDomainPrefix>.auth.<region>.amazoncognito.com/saml2/idpresponse |
4. Configure Attributes and Claims
Edit the attributes and claims to match your application requirements.
5. Add a Group Claim
Click Add a group claim
and select Groups assigned to the application
.
Creating a User
To test the integration, create a new user in Azure Entra ID:
1. Open the Users Section
Click New user
in the Azure portal.
2. Enter User Details
Fill in the required fields (e.g., username and name).
3. Add Email Address
Specify an email address for the user.
4. Skip Assignments
Skip the Assignments
tab for now.
5. Complete User Creation
Finalize the process to create the user.
Assigning a User to the Application
Once the user is created, assign them to the application:
1. Navigate to the Application
Select the my-cognito-app
enterprise application.
2. Assign Users and Groups
Click Assign users and groups
.
3. Add User/Group
Select Add user/group
and pick the user you created.
React App
Creating the Application
To create the frontend app, this post uses Next.js. Generate the app with the following command and options:
npx create-next-app@latest
✔ What is your project named? … amplify-with-cognito-and-entra-id
✔ Would you like to use TypeScript? … Yes
✔ Would you like to use ESLint? … Yes
✔ Would you like to use Tailwind CSS? … Yes
✔ Would you like to use `src/` directory? … Yes
✔ Would you like to use App Router? (recommended) … Yes
✔ Would you like to customize the default import alias (@/*)? … Yes
✔ What import alias would you like configured? … @/*
Change the working directory to the project root and install AWS Amplify with:
cd amplify-with-cognito-and-entra-id
npm i aws-amplify
Creating an Environment File
Create a .env.local
file in the root of your project with the following content. Replace the placeholders with your actual values:
<USER_POOL_ID>
<USER_POOL_CLIENT_ID>
<DOMAIN_PREFIX>
NEXT_PUBLIC_USER_POOL_ID=<USER_POOL_ID>
NEXT_PUBLIC_USER_POOL_CLIENT_ID=<USER_POOL_CLIENT_ID>
NEXT_PUBLIC_USER_POOL_ID_PROVIDER=azure-entra-id
NEXT_PUBLIC_OAUTH_DOMAIN=<DOMAIN_PREFIX>.auth.ap-northeast-1.amazoncognito.com
Updating the Main Page
Update the src/app/page.tsx
file with the following content to configure authentication and display user attributes:
'use client'
import { useEffect, useState } from 'react';
import { Amplify } from 'aws-amplify';
import { FetchUserAttributesOutput, fetchUserAttributes, getCurrentUser, signInWithRedirect, signOut } from 'aws-amplify/auth';
Amplify.configure({
Auth: {
Cognito: {
userPoolId: process.env.NEXT_PUBLIC_USER_POOL_ID as string,
userPoolClientId: process.env.NEXT_PUBLIC_USER_POOL_CLIENT_ID as string,
loginWith: {
oauth: {
domain: process.env.NEXT_PUBLIC_OAUTH_DOMAIN as string,
scopes: [
'email',
'openid',
'aws.cognito.signin.user.admin',
],
redirectSignIn: ['http://localhost:3000/'],
redirectSignOut: ['http://localhost:3000/'],
responseType: 'code',
},
},
},
},
});
export default function Home() {
const [attributes, setAttributes] = useState<FetchUserAttributesOutput>();
useEffect(() => {
(async () => {
try {
await getCurrentUser();
const attributes = await fetchUserAttributes();
setAttributes(attributes);
} catch (error) {
await signInWithRedirect({ provider: { custom: process.env.NEXT_PUBLIC_USER_POOL_ID_PROVIDER as string } });
}
})();
}, []);
return (
<div className='flex flex-col gap-2 max-w-sm mx-auto my-4'>
<div className='flex gap-2'>
<div>Sub:</div>
<div>{attributes?.sub}</div>
</div>
<div className='flex gap-2'>
<div>Name:</div>
<div>{attributes?.name}</div>
</div>
<div className='flex gap-2'>
<div>Email:</div>
<div>{attributes?.email}</div>
</div>
<button
type="button"
className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
onClick={() => signOut()}
>
Sign out
</button>
</div>
);
}
Testing the App
Start the development server with
npm run dev
Open http://localhost:3000/
in your browser. You will be redirected to a sign-in page.
After signing in, you can see the user attributes displayed in the app.
Verify that the user is created in the Cognito management console.
Cleaning Up
AWS Resources
Remove the provisioned AWS resources using the following command:
aws cloudformation delete-stack --stack-name amplify-with-cognito-and-entra-id
Azure Resources
Manually delete the enterprise application and any created users in Azure.
Conclusion
Federating Amazon Cognito with Azure Entra ID is an essential step for enterprises that rely on centralized identity management, particularly those using Active Directory. This integration allows for seamless, secure authentication workflows while leveraging existing organizational user directories.
In this guide, we’ve provided a comprehensive, step-by-step walkthrough of the integration process, covering both backend setup with AWS and Azure and frontend implementation using AWS Amplify.
If you’re interested in implementing Sign-in with Slack using Cognito, check out this related post:
I hope you find this guide helpful.
Happy Coding! 🚀