Skip to content

External Identity Provider (Federation)

This guide covers how to configure an external SAML or OIDC identity provider to federate authentication through Amazon Cognito for the GenAI IDP solution. Federated users sign in through their organization’s identity provider and are automatically mapped to Cognito groups (Admin, Author, Reviewer, Viewer) based on group claims from the IdP.

The GenAI IDP solution supports optional federation with external identity providers including:

  • PingOne (SAML or OIDC)
  • Okta (SAML or OIDC)
  • Microsoft Entra ID (Azure AD) (SAML or OIDC)

When federation is enabled:

  1. Users see a “Sign in with [IdP Name]” button on the Cognito hosted UI
  2. Clicking it redirects to the external IdP for authentication
  3. After successful authentication, the IdP sends group claims back to Cognito
  4. A post-authentication Lambda automatically maps IdP groups to Cognito groups
  5. The user is redirected to the GenAI IDP web UI with appropriate permissions

Native Cognito username/password authentication remains available alongside federation.

ConsiderationSAMLOIDC
Protocol maturityOlder, widely supported in enterpriseModern, lightweight
Setup complexitySlightly more involved (metadata XML, certificates)Simpler (client ID/secret + issuer URL)
Group claimsSent as SAML attributes in assertionSent as claims in ID token
Token formatXML-based assertionsJSON Web Tokens (JWT)
Best forEnterprise SSO with existing SAML infrastructureModern apps, simpler integration

Both work equally well with this solution. Choose based on what your IdP team prefers or what’s already configured in your organization.

ParameterRequiredDescription
ExternalIdPTypeYesSAML or OIDC (leave empty to disable)
ExternalIdPNameYesDisplay name (e.g., PingOne, Okta) — alphanumeric and hyphens only
ExternalIdPMetadataURLSAML onlySAML metadata document URL from your IdP
ExternalIdPOIDCIssuerOIDC onlyOIDC issuer URL (e.g., https://auth.pingone.com/<env-id>/as)
ExternalIdPOIDCClientIdOIDC onlyOIDC client ID from your IdP
ExternalIdPOIDCClientSecretArnOIDC onlyARN of a Secrets Manager secret containing the OIDC client secret (see Storing the OIDC Client Secret below)
ExternalIdPGroupAttributeNameOptionalAttribute/claim name carrying group membership
ExternalIdPAdminGroupNameOptionalIdP group name that maps to Cognito Admin role
ExternalIdPAuthorGroupNameOptionalIdP group name that maps to Cognito Author role
ExternalIdPReviewerGroupNameOptionalIdP group name that maps to Cognito Reviewer role
ExternalIdPViewerGroupNameOptionalIdP group name that maps to Cognito Viewer role
ExternalIdPAutoLoginOptionaltrue to auto-redirect to IdP, false (default) to show login page

For OIDC federation, the client secret must be stored in AWS Secrets Manager before deploying the stack. This ensures the secret never passes through CloudFormation parameters (which are visible via the describe-stacks API).

Create the secret:

Terminal window
aws secretsmanager create-secret \
--name "my-idp-oidc-client-secret" \
--description "OIDC client secret for GenAI IDP federation" \
--secret-string "YOUR_CLIENT_SECRET_HERE" \
--region us-east-1

Note the ARN from the output — you’ll pass it as the ExternalIdPOIDCClientSecretArn parameter during deployment.

To rotate the secret later:

Terminal window
aws secretsmanager update-secret \
--secret-id "my-idp-oidc-client-secret" \
--secret-string "NEW_CLIENT_SECRET_HERE"

Then redeploy the stack to pick up the new value.

Before configuring any external IdP, you need:

  1. A deployed GenAI IDP stack (deploy first with Cognito-only, then update with federation parameters)
  2. From the stack outputs, note:
    • User Pool ID — e.g., us-east-1_aBcDeFgHi
    • Cognito Domain — e.g., idp-1234567890.auth.us-east-1.amazoncognito.com
  3. Administrator access to your identity provider

The Cognito values you’ll need for IdP configuration:

  • SAML ACS URL: https://<cognito-domain>/saml2/idpresponse
  • SAML Entity ID: urn:amazon:cognito:sp:<user-pool-id>
  • OIDC Redirect URI: https://<cognito-domain>/oauth2/idpresponse

Step 1: Create a SAML Application in PingOne

Section titled “Step 1: Create a SAML Application in PingOne”
  1. Log in to the PingOne Admin Console
  2. Navigate to ConnectionsApplications
  3. Click + Add Application
  4. Select Web App, then choose SAML
  5. Enter an application name (e.g., GenAI IDP)
  6. Click Configure

In the SAML configuration:

  1. ACS URL:
    https://<cognito-domain>/saml2/idpresponse
  2. Entity ID:
    urn:amazon:cognito:sp:<user-pool-id>
  3. Binding Type: Select HTTP POST
  4. Signing: Enable response signing
  5. Click Save

In the application’s Attribute Mappings section, add:

PingOne AttributeSAML Attribute
Email Addresshttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
Group Nameshttp://schemas.xmlsoap.org/claims/Group

The Group Names attribute sends the user’s PingOne group memberships in the SAML assertion.

  1. Navigate to IdentitiesGroups
  2. Create groups that will map to GenAI IDP roles:
    • IDP-Admins
    • IDP-Authors
    • IDP-Reviewers
    • IDP-Viewers
  3. Assign users to the appropriate groups
  4. Ensure the application has access to these groups (check Policies if needed)
  1. Toggle the application to Enabled
  2. Go to ConfigurationConnection Details
  3. Copy the SAML Metadata URL — it looks like:
    https://auth.pingone.com/<environment-id>/saml20/metadata/<application-id>
Terminal window
idp-cli deploy \
--stack-name my-idp-stack \
--from-code . \
--parameters "\
ExternalIdPType=SAML,\
ExternalIdPName=PingOne,\
ExternalIdPMetadataURL=https://auth.pingone.com/<env-id>/saml20/metadata/<app-id>,\
ExternalIdPGroupAttributeName=http://schemas.xmlsoap.org/claims/Group,\
ExternalIdPAdminGroupName=IDP-Admins,\
ExternalIdPAuthorGroupName=IDP-Authors,\
ExternalIdPReviewerGroupName=IDP-Reviewers,\
ExternalIdPViewerGroupName=IDP-Viewers" \
--wait

Step 1: Create an OIDC Application in PingOne

Section titled “Step 1: Create an OIDC Application in PingOne”
  1. Log in to the PingOne Admin Console
  2. Navigate to ConnectionsApplications
  3. Click + Add Application
  4. Select Web App, then choose OIDC
  5. Enter an application name (e.g., GenAI IDP)
  6. Click Configure
  1. Grant Type: Select Authorization Code
  2. Redirect URI:
    https://<cognito-domain>/oauth2/idpresponse
  3. Token Endpoint Authentication Method: Client Secret Post or Client Secret Basic
  4. Scopes: Enable openid, email, profile
  5. Click Save

Step 3: Add a Custom Groups Scope (if needed)

Section titled “Step 3: Add a Custom Groups Scope (if needed)”

PingOne may not include group membership in tokens by default. To add it:

  1. Go to the application’s Resources tab
  2. Under Scopes, add a custom scope or enable the groups scope
  3. Alternatively, configure a custom claim:
    • Navigate to ResourcesCustom Attributes or Token Customization
    • Add a claim named groups that maps to the user’s group memberships

Same as SAML Step 4 above — create IDP-Admins, IDP-Authors, IDP-Reviewers, IDP-Viewers groups and assign users.

  1. Toggle the application to Enabled
  2. From the application’s Configuration tab, note:
    • Client ID
    • Client Secret
    • Issuer URL — typically:
      https://auth.pingone.com/<environment-id>/as
    You can verify the issuer by checking the well-known endpoint:
    https://auth.pingone.com/<environment-id>/as/.well-known/openid-configuration
Terminal window
idp-cli deploy \
--stack-name my-idp-stack \
--from-code . \
--parameters "\
ExternalIdPType=OIDC,\
ExternalIdPName=PingOne,\
ExternalIdPOIDCIssuer=https://auth.pingone.com/<env-id>/as,\
ExternalIdPOIDCClientId=<your-client-id>,\
ExternalIdPOIDCClientSecretArn=arn:aws:secretsmanager:us-east-1:123456789012:secret:my-pingone-oidc-secret-AbCdEf,\
ExternalIdPGroupAttributeName=groups,\
ExternalIdPAdminGroupName=IDP-Admins,\
ExternalIdPAuthorGroupName=IDP-Authors,\
ExternalIdPReviewerGroupName=IDP-Reviewers,\
ExternalIdPViewerGroupName=IDP-Viewers" \
--wait

  1. Log in to the Okta Admin Console
  2. Navigate to ApplicationsApplications
  3. Click Create App Integration
  4. Select SAML 2.0, click Next
  5. Enter an app name (e.g., GenAI IDP), click Next
  1. Single sign-on URL:
    https://<cognito-domain>/saml2/idpresponse
  2. Audience URI (SP Entity ID):
    urn:amazon:cognito:sp:<user-pool-id>
  3. Name ID format: EmailAddress
  4. Application username: Email

Add the following attribute statements:

NameValue
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddressuser.email

Add a Group Attribute Statement:

NameFilter
http://schemas.xmlsoap.org/claims/GroupMatches regex: IDP-.* (or adjust to match your group naming)
  1. Navigate to DirectoryGroups
  2. Create groups: IDP-Admins, IDP-Authors, IDP-Reviewers, IDP-Viewers
  3. Assign users to groups
  4. Go back to the application → Assignments tab → assign the groups to the app
  1. Go to the application’s Sign On tab
  2. Under SAML Signing Certificates, find the Metadata URL — or use:
    https://<your-okta-domain>/app/<app-id>/sso/saml/metadata
Terminal window
idp-cli deploy \
--stack-name my-idp-stack \
--from-code . \
--parameters "\
ExternalIdPType=SAML,\
ExternalIdPName=Okta,\
ExternalIdPMetadataURL=https://<okta-domain>/app/<app-id>/sso/saml/metadata,\
ExternalIdPGroupAttributeName=http://schemas.xmlsoap.org/claims/Group,\
ExternalIdPAdminGroupName=IDP-Admins,\
ExternalIdPAuthorGroupName=IDP-Authors,\
ExternalIdPReviewerGroupName=IDP-Reviewers,\
ExternalIdPViewerGroupName=IDP-Viewers" \
--wait

Step 1: Create an OIDC Application in Okta

Section titled “Step 1: Create an OIDC Application in Okta”
  1. Log in to the Okta Admin Console
  2. Navigate to ApplicationsApplications
  3. Click Create App Integration
  4. Select OIDC - OpenID Connect, then Web Application, click Next
  5. Enter an app name (e.g., GenAI IDP)
  1. Grant type: Authorization Code
  2. Sign-in redirect URI:
    https://<cognito-domain>/oauth2/idpresponse
  3. Sign-out redirect URI: Your web UI URL
  4. Assignments: Select the groups or users who should have access
  1. Navigate to SecurityAPIAuthorization Servers
  2. Select the default authorization server (or your custom one)
  3. Go to the Claims tab → Add Claim:
    • Name: groups
    • Include in token type: ID Token (Always)
    • Value type: Groups
    • Filter: Matches regex IDP-.* (or adjust to your naming)

From the application’s General tab:

  • Client ID
  • Client Secret
  • Issuer URL: https://<your-okta-domain>/oauth2/default
Terminal window
idp-cli deploy \
--stack-name my-idp-stack \
--from-code . \
--parameters "\
ExternalIdPType=OIDC,\
ExternalIdPName=Okta,\
ExternalIdPOIDCIssuer=https://<okta-domain>/oauth2/default,\
ExternalIdPOIDCClientId=<your-client-id>,\
ExternalIdPOIDCClientSecretArn=arn:aws:secretsmanager:us-east-1:123456789012:secret:my-okta-oidc-secret-AbCdEf,\
ExternalIdPGroupAttributeName=groups,\
ExternalIdPAdminGroupName=IDP-Admins,\
ExternalIdPAuthorGroupName=IDP-Authors,\
ExternalIdPReviewerGroupName=IDP-Reviewers,\
ExternalIdPViewerGroupName=IDP-Viewers" \
--wait

  1. Log in to the Azure Portal
  2. Navigate to Microsoft Entra IDEnterprise applications
  3. Click New applicationCreate your own application
  4. Enter a name (e.g., GenAI IDP), select Integrate any other application, click Create
  1. Go to Single sign-on → select SAML
  2. Edit Basic SAML Configuration:
    • Identifier (Entity ID):
      urn:amazon:cognito:sp:<user-pool-id>
    • Reply URL (ACS URL):
      https://<cognito-domain>/saml2/idpresponse
  3. Click Save
  1. Click Edit on Attributes & Claims
  2. Verify the email claim exists:
    • Claim name: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
    • Source attribute: user.mail
  3. Add a group claim:
    • Click Add a group claim
    • Select Security groups or Groups assigned to the application
    • Under Advanced options, check Customize the name of the group claim
    • Name: http://schemas.xmlsoap.org/claims/Group
    • Source: Group ID (or Display Name if you prefer readable names)

Note: If using Group IDs, your ExternalIdPAdminGroupName etc. parameters must use the Entra group object IDs (GUIDs) rather than display names.

  1. Navigate to Microsoft Entra IDGroups
  2. Create groups: IDP-Admins, IDP-Authors, IDP-Reviewers, IDP-Viewers
  3. Add users to groups
  4. Go back to the Enterprise Application → Users and groups → assign the groups
  1. Go to Single sign-onSAML Certificates section
  2. Copy the App Federation Metadata Url — it looks like:
    https://login.microsoftonline.com/<tenant-id>/federationmetadata/2007-06/federationmetadata.xml?appid=<app-id>
Terminal window
idp-cli deploy \
--stack-name my-idp-stack \
--from-code . \
--parameters "\
ExternalIdPType=SAML,\
ExternalIdPName=EntraID,\
ExternalIdPMetadataURL=https://login.microsoftonline.com/<tenant-id>/federationmetadata/2007-06/federationmetadata.xml?appid=<app-id>,\
ExternalIdPGroupAttributeName=http://schemas.xmlsoap.org/claims/Group,\
ExternalIdPAdminGroupName=IDP-Admins,\
ExternalIdPAuthorGroupName=IDP-Authors,\
ExternalIdPReviewerGroupName=IDP-Reviewers,\
ExternalIdPViewerGroupName=IDP-Viewers" \
--wait

  1. Log in to the Azure Portal
  2. Navigate to Microsoft Entra IDApp registrations
  3. Click New registration
  4. Enter a name (e.g., GenAI IDP)
  5. Redirect URI: Select Web and enter:
    https://<cognito-domain>/oauth2/idpresponse
  6. Click Register
  1. Go to Certificates & secretsNew client secret
  2. Add a description and expiration
  3. Copy the Value (this is your client secret — it’s only shown once)
  1. Go to Token configurationAdd groups claim
  2. Select Security groups (or Groups assigned to the application)
  3. For ID token, select Group ID
  4. Click Add
  1. Go to API permissions
  2. Ensure these are granted:
    • openid
    • email
    • profile
  • Client ID: From the app’s Overview page
  • Client Secret: From Step 2
  • Issuer URL:
    https://login.microsoftonline.com/<tenant-id>/v2.0
Terminal window
idp-cli deploy \
--stack-name my-idp-stack \
--from-code . \
--parameters "\
ExternalIdPType=OIDC,\
ExternalIdPName=EntraID,\
ExternalIdPOIDCIssuer=https://login.microsoftonline.com/<tenant-id>/v2.0,\
ExternalIdPOIDCClientId=<your-client-id>,\
ExternalIdPOIDCClientSecretArn=arn:aws:secretsmanager:us-east-1:123456789012:secret:my-entraid-oidc-secret-AbCdEf,\
ExternalIdPGroupAttributeName=groups,\
ExternalIdPAdminGroupName=<admin-group-object-id>,\
ExternalIdPAuthorGroupName=<author-group-object-id>,\
ExternalIdPReviewerGroupName=<reviewer-group-object-id>,\
ExternalIdPViewerGroupName=<viewer-group-object-id>" \
--wait

Note: Entra ID OIDC sends group object IDs (GUIDs) by default, not display names. Use the group object IDs from the Azure Portal as your mapping values.


After deploying with federation parameters:

  1. Navigate to the GenAI IDP web UI
  2. The Cognito hosted UI should show a button labeled with your IdP name (e.g., “PingOne”)
  3. Click it to be redirected to your IdP for authentication
  4. After signing in, you should be redirected back to the GenAI IDP web UI
  5. Verify your role matches your IdP group membership by checking the user profile

To revert to Cognito-only authentication, update the stack and set ExternalIdPType back to empty:

Terminal window
idp-cli deploy \
--stack-name my-idp-stack \
--from-code . \
--parameters "ExternalIdPType=" \
--wait

This removes the external identity provider, the group mapping Lambda, and reverts the User Pool Client to Cognito-only. Existing Cognito-native users are unaffected.

IssueCauseSolution
”Invalid saml_response” errorACS URL or Entity ID mismatchVerify they match exactly between your IdP and Cognito
User signs in but has no permissionsGroup claim not mapped or group names don’t matchCheck ExternalIdPGroupAttributeName matches the IdP attribute name, and group names are case-sensitive exact matches
Redirect loop after sign-inCallback URL mismatchEnsure the Cognito User Pool Client callback URL includes your web UI URL (with and without trailing slash)
“Invalid_grant” error (OIDC)Client secret incorrect or expiredRegenerate the client secret in your IdP and update the stack parameter
Groups not appearing in tokenIdP not configured to send groupsCheck IdP group claim configuration (see provider-specific steps above)
“Application is not enabled” (PingOne)PingOne app is disabledToggle the application to Enabled in PingOne admin console
”Unsupported authentication method” (PingOne OIDC)Token endpoint auth method mismatchSet PingOne OIDC app to Client Secret Post
”RedirectUri is not registered”Callback URL trailing slash mismatchEnsure both with and without trailing slash variants are registered
User disabled but can still sign inIdP SSO session still active in browserRevoke the user’s active sessions in the IdP admin console, or wait for the SSO session to expire
Sign out signs user back in (auto-login)IdP SSO session persists after Cognito logoutExpected behavior with auto-login enabled — see Auto-Login Behavior below

When ExternalIdPAutoLogin is enabled:

  • Users are automatically redirected to the external IdP when visiting the app
  • Sign-out clears the Cognito session and redirects through Cognito’s logout endpoint
  • If the IdP SSO session is still active, the user may be automatically signed back in on the next visit
  • This is standard SSO behavior — the IdP controls session lifetime, not the app
  • To fully sign out, users must also sign out of their IdP (e.g., PingOne, Okta, Entra ID)
  • Organizations can control this by configuring SSO session timeouts in their IdP
  • Set ExternalIdPAutoLogin to false if your organization requires explicit sign-in on each visit

The ExternalIdPGroupMappingFunction logs every federated sign-in with group mapping details. Check CloudWatch Logs for the function to debug group mapping issues:

Terminal window
aws logs tail /aws/lambda/<stack-name>-ExternalIdPGroupMappingFunction-<id> --follow