Skip to content
TerminalBytes
Go back

Azure AD as an Identity Provider for AWS Cognito

Updated:
On this page

A client asked me to wire their existing Azure Active Directory tenant into a new AWS Cognito user pool so their employees could sign in to a custom app using their Microsoft credentials. The official AWS docs cover the generic SAML/OIDC setup; the official Azure docs cover the AAD side. Neither walks you end-to-end through the actual integration, with the gotchas that show up when the two products meet in the middle.

This post is the playbook I now hand to anyone doing the same integration. Two paths: SAML 2.0 (faster to set up, fewer features) and OpenID Connect (more flexible, supports cross-tenant and personal Microsoft accounts). Pick one based on your tolerance for B2B and personal-account complexity.

Azure AD integration with AWS Cognito as IDP using SAML 2.0 and OIDC

TL;DR: SAML 2.0 if all your users are in one Azure AD tenant. OIDC if you need to support multiple tenants, personal Microsoft accounts (@outlook.com, @hotmail.com), or guest users. Both work; they’re just different shapes of the same handshake.

SAML vs OIDC: which path to pick

Both protocols solve the same problem: AWS Cognito wants to verify a user’s identity, Azure AD has the source of truth, and both speak a federation protocol. The choice between them is mostly about scope.

Pick SAML 2.0 if:

  • All users live in a single Azure AD tenant.
  • You’re comfortable manually creating the Enterprise Application in the Azure portal.
  • You don’t need to support personal Microsoft accounts (@hotmail.com, @live.com, @outlook.com). SAML enterprise apps don’t.

Pick OIDC if:

  • Users may come from multiple Azure AD tenants (B2B scenarios).
  • You need to support personal Microsoft accounts.
  • You want the integration scriptable. Azure’s CLI can create OIDC App Registrations but can’t yet create SAML enterprise apps.

Both protocols arrive at the same place: a verified user in the Cognito user pool with claims you’ve mapped to attributes. The plumbing is what differs.

Prerequisites for either path

Before you start either flow, line up:

  • An Azure AD tenant with admin access. Premium isn’t strictly required for OIDC; SAML enterprise apps work on the free tier today, contrary to older docs.
  • An existing AWS Cognito user pool with a configured Cognito domain (the xxx.auth.<region>.amazoncognito.com URL).
  • The Azure tenant ID (only required for OIDC). Find it under Azure AD → Overview.
  • An app client inside the Cognito user pool, with at least one callback URL configured. This is the redirect target after a successful sign-in.

You’ll be jumping between the Azure Portal and the AWS Cognito console quite a bit. Open both in adjacent browser tabs.

SAML 2.0: create the Azure AD enterprise application

The SAML flow starts on the Azure side. You create an Enterprise Application that represents your Cognito user pool, configure the SAML response, and download the metadata XML that Cognito will import.

  1. Go to Azure Portal → Azure Active Directory → Enterprise Applications → New Application.
  2. Pick Create your own application, give it a name, and select Integrate any other application you don’t find in the gallery (Non-gallery).
  3. Open the new app, then Single sign-on → SAML.
  4. In Basic SAML Configuration, set:
    • Identifier (Entity ID): urn:amazon:cognito:sp:<your-cognito-user-pool-id> (e.g. urn:amazon:cognito:sp:us-east-1_AbCdEfGhI).
    • Reply URL (ACS URL): https://<your-cognito-domain>.auth.<region>.amazoncognito.com/saml2/idpresponse (substitute your real domain and region).
  5. Under User Attributes & Claims, leave the default Unique User Identifier mapping in place. Verify these four claims are present and pointing at the right Azure AD user fields:
Claim namespaceSource attribute
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddressuser.userprincipalname
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givennameuser.givenname
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameuser.displayname
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surnameuser.surname
  1. Under SAML Signing Certificate, download the Federation Metadata XML. You’ll upload this to Cognito.

That’s the Azure side done. The metadata XML is the contract: it contains Azure AD’s signing certificate and endpoints, which Cognito uses to verify the SAML responses.

SAML 2.0: register Azure AD in Cognito and map claims

Switch to the AWS Cognito console.

  1. Go to your user pool → Sign-in experience → Federated identity provider sign-in → Add identity provider → SAML.
  2. Give the provider a name (this is what shows up on the Cognito hosted UI button, so something like AzureAD).
  3. Upload the Federation Metadata XML you downloaded from Azure.
  4. Add attribute mappings. The SAML claim namespaces are long; Cognito uses short names:
SAML attribute (from Azure)Cognito user pool attribute
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddressemail
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givennamegiven_name
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surnamefamily_name
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/namename
  1. Save the provider.
  2. Go to App integration → App client list → your client → Hosted UI. Enable the new AzureAD provider in the Identity providers section. Make sure Authorization code grant and Implicit grant are checked under OAuth 2.0 if your app uses them.

Test by hitting the Cognito hosted login URL:

https://<cognito-domain>.auth.<region>.amazoncognito.com/login?
  response_type=token&
  client_id=<cognito-app-client-id>&
  redirect_uri=<cognito-callback-url>

You should see your Cognito hosted UI with a “Sign in with AzureAD” button. Click it, sign in with an Azure AD user that’s been assigned to the enterprise app, and you’ll get redirected back to your callback with tokens in the URL fragment. If something goes wrong, the Azure AD sign-in logs (in the enterprise app) and the Cognito CloudWatch logs are where to look.

SAML gotchas worth knowing

Three things will trip you up on the SAML path. I’ve hit each of them on real client work.

Personal accounts don’t work. Azure Enterprise Applications can’t authenticate users on @live.com, @hotmail.com, @outlook.com. If your user base includes any of those, switch to OIDC. There’s a Stack Overflow thread that documents this clearly; the constraint hasn’t been lifted as of this writing.

You must assign users to the app. Azure won’t let users sign in to a SAML enterprise app unless they (or a group they belong to) is assigned. Go to the app → Users and groups → Add user/group. New employees added to AAD won’t auto-pick up the app unless you assign them via a group.

The Reply URL is region-specific. amazoncognito.com URLs include the AWS region in the hostname. Get the region wrong and you’ll spend an hour wondering why SAML responses fail with no useful error. Triple-check the URL.

OIDC: create the Azure AD App Registration

The OIDC path uses App Registrations instead of Enterprise Applications. App Registrations are scriptable via the Azure CLI, support multi-tenant and personal accounts, and are what Microsoft now recommends for new integrations.

  1. Go to Azure Portal → Azure Active Directory → App Registrations → New Registration.
  2. Give the app a name. Under Supported account types, pick the option that matches your needs:
    • Single tenant: only your AAD tenant can sign in.
    • Multi-tenant: any AAD tenant can sign in (good for B2B).
    • Multi-tenant + personal: any AAD tenant plus personal Microsoft accounts.
  3. Set the Redirect URI to https://<your-cognito-domain>.auth.<region>.amazoncognito.com/oauth2/idpresponse. Choose Web as the platform.
  4. Click Register.
  5. From the app’s overview page, copy the Application (client) ID. You’ll need this in Cognito.
  6. Go to Certificates & secrets → New client secret. Set an expiry (1 year is reasonable; you’ll have to rotate before then). Copy the secret value immediately; Azure only shows it once.
  7. Optional but recommended: under API permissions, ensure openid, profile, and email are granted. They are by default for new apps, but worth verifying.

OIDC: add the provider in Cognito and map attributes

Back in the AWS Cognito console:

  1. Go to your user pool → Sign-in experience → Federated identity provider sign-in → Add identity provider → OpenID Connect.
  2. Set:
    • Provider name: a string for the Cognito UI button, e.g. AzureAD-OIDC.
    • Client ID: the Application (client) ID you copied from Azure.
    • Client secret: the secret you copied from Azure.
    • Attribute request method: GET.
    • Authorize scopes: profile email openid.
    • Issuer: https://login.microsoftonline.com/<tenant-id>/v2.0 (substitute your tenant ID).
  3. Click Run discovery to let Cognito pull Azure’s OIDC endpoints. If it succeeds, the dialog populates the well-known endpoints automatically.
  4. Save.
  5. Add attribute mappings under the new OIDC provider:
OIDC claimCognito attribute
subusername
emailemail
namename
unique_namegiven_name
preferred_usernamepreferred_username
  1. Enable the OIDC provider in the App client → Hosted UI section, same as the SAML flow.

For personal Microsoft accounts, create a second OIDC provider with the issuer set to https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0. That magic GUID is the static tenant ID Microsoft uses for personal accounts; it’s published in Microsoft’s identity platform docs.

Common attribute-mapping problems

The Cognito-side mapping is where most integration bugs live. The OIDC claims Azure returns aren’t standardised between AAD setups, so you’ll occasionally see surprises.

Email is missing or blank. Some AAD setups don’t populate the email claim, especially when users sign in with @partner-domain.com UPNs. Check the Cognito user record after a test sign-in (User Pool → Users) and look at the raw attributes. If email is empty, look for preferred_username or unique_name to contain something email-shaped, then remap that field to Cognito’s email attribute.

Name fields don’t match. AAD’s name is the user’s display name (first + last); given_name and family_name come from unique_name and family_name respectively. If your front-end shows display names from given_name, you’ll see weird “Alice Doe Alice Doe” duplication. Always log in once and inspect the actual claim payload before locking the mapping in.

Cognito refuses to create the user. If the user pool requires email as a verified attribute and Azure isn’t returning it, Cognito rejects the user with a not-very-helpful error. Either remap a different claim into email, or remove the email requirement on the user pool’s attribute config.

After everything works, verify by signing in with a test user and checking the Cognito user pool’s user list. The user should appear with all the expected attributes populated. If a field is empty, the mapping is wrong; fix it and try a fresh sign-in (existing users won’t update on subsequent logins by default).

If this saved you an afternoon of digging through AWS docs, my WordPress on Google Cloud free tier post takes the same “stitching two cloud products together” approach, the Linux text-manipulation commands post covers the grep/awk skills that pay off when you’re parsing federation logs in CloudWatch, and the common Linux commands for system monitoring cover the in-shell tools you’ll want when the Cognito service stutters.

Federation tools always look simple in the marketing materials. The real work is the attribute mapping. Get that right and the rest follows.

Last updated: March 2024