Prescriptive guide to setting up Amazon Cognito identity federation from SAML identity provider, i.e. ADFS or AD
Sample web application provided in this repo demonstrates how to use AWS Amplify with a Cognito User Pool which is integrated with a SAML identity provider (ADFS). Before the web application can be used, Cognito and ADFS must be configured properly. This document:
An highlevel overview of Cognito <> ADFS <> User interactions is shown in the diagram below. In Identity Provider Setup and Cognito Setup sections, below, we will standup the ADFS infrastructure and configure both ADFS and Cognito.
But first, let's dive slightly deeper into both the login and logout flows and understand the various interactions between Cognito (relaying party or RP) and ADFS (oauth provider or OP). Refer to
/login
end-point; user is redirected to Cognito Hosted UI. Alternatively, user (or application) can directly trigger the federated sign-in process by invoking Cognito end-point /oauth/authorize
. Refer to Cognito Endpoints./logout
end-pointSAML Logout Endpoint Trusted URL
with a signed SAML sign-out request.SAML Logout Endpoint Response URL
. This response URL is Cognito's SAML logout endpoint (more details in ADFS section)Sign out URL
configured in the Cognito application client settingA SAML Identity Provider (idP), i.e. ADFS, must be properly configured such that Amazon Cognito can receive SAML request from idP for authentication and user pool federation, and such that idP can also receive signed SAML requests from Amazon Cognito to logout a user.
Lets start by installing Web Application Proxy, ADFS and Domain Controllers on AWS EC2 instances. For this exercise, use the Web Application Proxy Quickstart on AWS. Install the quick start CloudFormation template in your AWS account.
Once the installation completes, log into AWS Console and bring up EC2 dashboard. Locate RDPGW, WAP1, ADFS1, DC1 instances. Note down the public and private IP addresses of these instances.
IMPORTANT: As soon as the Web Application Proxy is installed, you will start incurring
charges. Be mindful of the ~7 EC2 instances that this template starts and installs MS
ADFS and WAP.
IMPORTANT: When deploying the Web Application Proxy Quickstart template, make sure that
your ADFS passwords do not contain any special characters. Keep those passwords to a
mix of alphanumeric characters and save yourself hours of pain.
IMPORTANT: The Web Application Proxy Quickstart template installation prompts for a
domain name to associate with the installation. Make sure that it is a valid domain
name registered with your choice of DNS service providers. We will create A Record
for this domain name to point to ADFS Web Application Proxy once the setup is complete.
Follow these steps to configure ADFS:
Add Relaying Party Trust
. It will launch a wizard. Select Enter data manually
. Input the following parameters:
Amazon Cognito
AD FS Profile
Enable support for the SAML 2.0 WebSSO protocol
box. Enter https://<domain_prefix>.auth.<region>.amazoncognito.com/saml2/idpresponse
where domain_prefix is Cognito domain in app client and region is where Cognito user pool was created. Refer to Cognito configuration section for more detailsurn:amazon:cognito:sp:<user_pool_id>
to the list, where user_pool_id is obtained from your Cognito user pool configurationPermit All Users
on the last screenAmazon Cognito
RP (Relaying Party) created above
Transform an Incoming Claim
Name ID
Windows account name
Name ID
Persistent Identifier
Pass through all claim values
selectedSend LDAP Attributes as Claims
Email
Active Directory
E-Mail-Addresses
E-Mail Address
Get-AdfsProperties
to get ADFS properties; one of the properties is the login URL for ADFS that is publically accessible. Note that the URL will be in this format https://sts.<your_domain>/adfs/ls
. Once ADFS and Cognito configuration are done, use the login URL to test ADFS login is successful. The Login URL is https://sts.<your_domain>/adfs/ls/idpinitiatedsignon.htm
Enable
. Now you should be able to navigate to https://sts.<your_domain>/adfs/ls/idpinitiatedsignon.htm
in your browser, and see the RP appear in a dropdown.Set-AdfsProperties –EnableIdpInitiatedSignonPage $True
Follow these steps to configure DC1 (primary domain controller):
your domain
> Users. Right click on users and create new users
@your_domain
@your_domain
Email
attribute in user properties screen.Referring to the Web Application Proxy Quickstart on AWS
section above, the installation assumes a resolvable domain name. Create DNS A Record
to point the public IP address of WAP1 and WAP1. It is normal to have two A Records created for a domain. This is a cheap way to perform DNS based load balancing.
nslookup domain_name
to resolve the domain. It should resolve to two IP addresses.Download the Metadata XML file that will be used in the following section to configure Cognito SAML Identity Provider.
https://sts.<domain_name>/FederationMetadata/2007-06/FederationMetadata.xml
sts.<domain_name>
When idP Sign out flow
is enabled in Cognito SAML idP setting, ADFS must be configured with Cognito signing certificate. This is because Cognito will send a signed signout/logout SAML request to ADFS logout endpoint. ADFS must also be configured to listen on a SAML Logout end-point where Cognito will post the signout/logout SAML request to.
This can be done in two ways, using aws CLI or from Cognito dashboard. Lets cover the CLI:
Ensure that aws
cli is setup with appropriate security keys for your AWS account where Cognito User Pool is created and SAML idP is configured.
Run the following command to extract Cognito signing certificate. This certificate contains the public key that is used by idP (ADFS) to verify the signed signout/logout SAML request Cognito sends.
aws cognito-idp get-signing-certificate --user-pool <your user pool id> > cognito.crt
Transfer the cognito.crt
file to ADFS1 primary node.
Alternatively, the certificate is also visible in Cognito Dashboard. Go to Federation > Identity Providers > SAML > Active SAML Providers and click on show signing certificate
. Copy / paste the contents into a file cognito.crt
.
cogito.crt
file (above) is available on the local windows file system on ADFS1. You can leverage the clipboard to copy and paste the content of the file to the RDP session.AD FS Management
applicationAmazon Cognito
Relaying Party (or the name of your RP you created in previous steps for Cognito). Double click on the RP to bring up its properties.Signature
tab.Add
button and import the cognito.crt
signing certificate. If you don't see your .crt
file, make sure you select All Files("*")
at the bottom right of the file selection popup.Install Certificate
buttonLocal Machine
under Store Location
. Click Next
.Place certificate in following store
and click Browse
buttonSelect Certificate Store
dialog, choose Trusted Root Certificate Authorities
and click OK
button.Next
and then Finish
buttons to complete certificate installation.As a precaution and in order to avoid ADFS exception ID4037: The key needed to verify the signature could not be resolved
when Cognito triggers the idP signout flow, disable the ADFS revocation checks as follows:
Launch Windows PowerShell in ADFS1
List all relaying parties and revocation check settings using Windows PowerShell:
Get-AdfsRelyingPartyTrust | Select-Object Identifier, SigningCertificateRevocationCheck, EncryptionCertificateRevocationCheck
Disable Revocation Check as follows. Note that the Identifier URL
is visible in the previous command. It is the identifier URL that was set in ADFS configuration earlier and is in the format urn:amazon:cognito:sp:<user_pool_id>
Get-AdfsRelyingPartyTrust -Identifier <Identifier URL> | Set-AdfsRelyingPartyTrust -SigningCertificateRevocationCheck None -EncryptionCertificateRevocationCheck None
While still in ADFS1 node
AD FS Management
applicationAmazon Cognito
RP or the one you created above. Double click on it to bring its propertiesEndpoints
tabAdd SAML
button.SAML Logout
POST
https://sts.<your_domain>/adfs/ls
https://<yourDomainPrefix>.auth.<region>.amazoncognito.com/saml2/logout
Amazon Cognito
RP.This section assumes that a Cognito User Pool exists and it will be configured with SAML idP. If a user pool does not exist, create one with default values. Note down the User Pool Id
as it will be used in following sections.
Also, note that there are two App Clients needed, one for React Web applicaiton and another for Swift iOS native application.
Generate client secret
is unchecked. Note down the App client id
of the new app client. This will be used later.https://<domain prefix>.auth.us-east-1.amazoncognito.com
.Go to Federation > Identity Providers. Click SAML
Under Add Metada Document
provide the the URL of FederationMetada.xml document. For example:
https://sts.<domain_name>/FederationMetadata/2007-06/FederationMetadata.xml
Alternatively, upload the downloaded FederationMetadata.xml
document from the previous sections.
Set the Provider Name to something meaningful, e.g. adfs
Check Enable idP sign out flow
Save the new SAML provider settings
adfs
(your new SAML provider) under Enabled Id Provider
Sign in and sign out URLs
set as follows (note these URLs use localhost
hostname which is only used in development configuration. In a production configuration, the URLs will point to a Route53 or CloudFront enabled application URL)
OAuth 2.0
, select Authorization code grant
and Implicit grant
Allowed OAuth Scopes
, only check phone
, email
, openid
, and profile
. Don't select aws.cognito.signin.user.admin
if you don't want the users to have the ability to perform admin functionalities such as changing passwords. In our case, since users are managed in the Active Directory, we don't want this box checked. Refer to the blog post for more details.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
(you can refer to FederationMetadata.xml downloaded earlier for more information on the claim and exact url. If there are other claims you want to map, refer to this file.)Email
Note: It is possible to capture custom User Pool attributes here as well. To map custom attributes, make sure that the custom attributes are both read and write enabled by going to General Setting > App Clients > Show Details > Set attribute read and write permissions. Select the custom attribute in both read and write columns and hit Save app client changes
Identity Pool is needed by AWS Amplify SDK used in the React web application. It is used to pass temporary AWS credentials such that the idP user signed into web application via Cognito is able to invoke AWS services (AppSync, S3 etc) without needing an actual IAM user.
Federated Identities
Create new identity pool
. Assign a unique identify pool nameAuthentication Providers
. Click on CognitoUser Pool ID
and App client id
values. These were created earlier in this section.Create Pool
button.In order to authenticate with Amazon Cognito, which is configured with a SAML idP, certain assumptions are made about the web application.
The sample React Web Application uses AWS Amplify framework.
The first step in configuring AWS Amplify for the sample web application is to edit src/config.jsx
. Update configuration file properties (below) to match your Cognito configuration before launching or deploying the application. Contact your infrasrtructure team (or the person responsibile for setting up Cognito and ADFS authentication as documented earlier) to get the values for each of the following fields.
AWS_REGION
: cognito pool region,AWS_COGNITO_IDENTITY_POOL_ID
: identity pool idAWS_COGNITO_USER_POOL_ID
: user pool idAWS_COGNITO_CLIENT_ID
: app client idAWS_COGNITO_CLIENT_DOMAIN_NAME
: domain nameAWS_COGNITO_IDP_NAME
: SAML Identity Provider nameAWS_COGNITO_IDP_SIGNIN_URL
: sign in URL (this is web application url that will initialize AWS Amplify SDK)AWS_COGNITO_IDP_SIGNOUT_URL
: sign out URLAWS_COGNITO_IDP_GRANT_FLOW
: possible values are 'code' or 'token'Refer to src/index.jsx
and review how AWS Amplify is configured (code snippet below) before the sample React Web Application starts. Note that the variables defined in src/config.jsx
are imported and used in AWS Amplify initialization.
import Amplify from 'aws-amplify';
import AWS from 'aws-sdk';
import config from './config';
//AWS SDK & AWS Amplity Configuration
AWS.config.region = config.AWS_REGION;
Amplify.configure({
Auth: {
identityPoolId: config.AWS_COGNITO_IDENTITY_POOL_ID, // REQUIRED - Amazon Cognito Identity Pool ID
region: config.AWS_REGION, // REQUIRED - Amazon Cognito Region
userPoolId: config.AWS_COGNITO_USER_POOL_ID, //OPTIONAL - Amazon Cognito User Pool ID
userPoolWebClientId: config.AWS_COGNITO_CLIENT_ID, //OPTIONAL - Amazon Cognito Web Client ID
oauth: {
domain: config.AWS_COGNITO_CLIENT_DOMAIN_NAME,
scope: config.AWS_COGNITO_IDP_OAUTH_CLAIMS,
redirectSignIn: config.AWS_COGNITO_IDP_SIGNIN_URL,
redirectSignOut: config.AWS_COGNITO_IDP_SIGNOUT_URL,
responseType: config.AWS_COGNITO_IDP_GRANT_FLOW
}
}
});
Review the rest of the sample React Web Application to understand how AWS Amplify is used to perform authentication against Cognito, which is configured with iDP (ADFS). Once the AWS Amplify is configured and initialized, it is trival to invoke AWS AppSync calls from the web application. Refer to AWS Amplify GraphQL Endpoint documentation for more details.
TBD