Setting up an Azure AD identity provider in AWS Cognito

This post describes step-by-step how to set up an AWS Cognito User Pool with an Azure AD identity provider to allow your application to leverage single sign-on with Azure AD.

In order to get started, you need the following in place:

  • Azure account with Azure AD Premium enabled
  • AWS account
  • URL for the application that you will be integrating to Cognito (e.g. https://myapp.nordcloud.com)

The setup consist of 3 steps:

  1. Create an AWS Cognito user pool
  2. Create an Azure AD enterprise application
  3. Set up Azure AD identity provider to the Cognito User Pool

The federation is based on SAML, with the following login flow:

  1. The user lands on a page hosted by AWS Cognito (e.g. redirected by your application)
  2. Cognito redirects the user to an Azure AD login page (may have other identity providers available for selection)
  3. Azure AD passes the identity to Cognito, which redirects the user to the application login page with the access_token in the URL.

 

Create an AWS Cognito User Pool

In AWS, create a Cognito User pool with an application client. Otherwise, use the default settings. Memorise the Pool Id (e.g. us-east-1_P5fyukyC1I).

Screen Shot 2017-12-12 at 14.28.14

Screen Shot 2017-12-12 at 14.29.29

Add a domain for your Cognito application (e.g. mpu201712). Memorize the domain URL (e.g. https://mpu201712.auth.us-east-1.amazoncognito.com)

Screen Shot 2017-12-12 at 14.31.39

Create an Azure AD Enterprise Application

In Azure, create an Azure AD Enterprise Application, (requires Azure AD Premium) from your Azure AD blade -> Enterprise Applications -> New Application. Pick “Non-gallery application” as the app type.

Screen Shot 2017-12-12 at 14.33.49

Add a user to your application and configure Single sign-on with the following settings:

Screen Shot 2017-12-12 at 14.38.04

Finally, download the SAML Metada XML. You should now be set up on the Azure side.

 

Configure the Azure AD Identity Provider to Your Cognito Pool

In AWS, create a new SAML identity provider for your Cognito pool. Upload the SAML metadata downloaded for your Azure AD Enterprise App.

Screen Shot 2017-12-12 at 14.40.56

Add attribute mapping for email address (and other attributes you need).

  • SAML Attribute: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
  • User pool Attribute: Email

Screen Shot 2017-12-12 at 14.43.52

Enable the identity provider created above for your cognito pool from App client settings. Add your app callback and signout URLs (e.g. https://myapp.nordcloud.com/login), enable the following oAuth 2.0 flows and scopes: code grant, implicit grant, email, openid, aws.cognito.signin.user.admin. Memorise the app client id (7hosfpqdh003qrng4hsu2ionjk)

Screen Shot 2017-12-12 at 14.46.26

You should now be set up and ready to test the setup.

Testing your setup

Enter the Cognito login page URL to your browser. It is located at a URL of format:

https://<cognito domain>/login?response_type=token&client_id=<app client id>&scope=<oauth scope>&redirect_uri=<your encoded redirect URI>

For example:

https://mpu201712.auth.us-east-1.amazoncognito.com/login?response_type=token&client_id=7hosfpqdh003qrng4hsu2ionjk&scope=email+openid&redirect_uri=https%3A%2F%2Fmyapp.nordcloud.com%2Flogin

Log in with your Azure AD credentials. You should redirected to your callback URL configured for your Cognito app and provided as the redirect URL  (e.g. https://myapp.nordcloud.com/login) with the access token stored in the id_token parameter. For example:

https://myapp.nordcloud.com/login#id_token=eyJraWQiOiJoU2lXcjFySFE0T3FsbDJVVkQ3MUZLWFcrSlVzcG9UOGUwRzR2YloybEJVPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiIwNzQ4ZTRlMC0wZTgzLTQ5ZjYtODFkYS1kYzFmNDY4ZTM3ZmQiLCJhdWQiOiI3aG9zZnBxZGgwMDNxcm5nNGhzdTJpb25qayIsImNvZ25pdG86Z3JvdXBzIjpbInVzLWVhc3QtMV9QNWZ5dWt5QzFfQUQtTXB1MjAxNzEyIl0sImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiaWRlbnRpdGllcyI6W3sidXNlcklkIjoibWlrYWVsLnB1aXR0aW5lbkBzYzUuaW8iLCJwcm92aWRlck5hbWUiOiJBRC1NcHUyMDE3MTIiLCJwcm92aWRlclR5cGUiOiJTQU1MIiwiaXNzdWVyIjoiaHR0cHM6XC9cL3N0cy53aW5kb3dzLm5ldFwvYTliNjcyNmEtNmMwMC00ZmQ2LWFhMjAtMTdkNzY5NmM5NTRlXC8iLCJwcmltYXJ5IjoidHJ1ZSIsImRhdGVDcmVhdGVkIjoiMTUxMzA4MTM3NDk1NCJ9XSwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE1MTMwODE3NzQsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX1A1Znl1a3lDMSIsImNvZ25pdG86dXNlcm5hbWUiOiJBRC1NcHUyMDE3MTJfbWlrYWVsLnB1aXR0aW5lbkBzYzUuaW8iLCJleHAiOjE1MTMwODUzNzQsImlhdCI6MTUxMzA4MTc3NCwiZW1haWwiOiJtaWthZWwucHVpdHRpbmVuQHNjNS5pbyJ9.q6iMvWDZ6o-e_xFhIoQ21ssIHnF9Ujznc1tSSeWiaNFbhK8e7HJBGOx8-NVy7cfnLyjPSnxuO5rUqlUQM-dFjQkuouK62VcAbS7wpIH7-6dKWtLzQTmUGHtLO7Us331GT6aEAOSy7Zbw63ZXl-vIrvnyqCv0XOLvMhqOIUiExiEumettW-m-6jZ0jedimQij8-UituR__iAPaM2yOPD24Yz5tWvIf-QHQUZ3FZyasDSKo-S9jUclqUInZYeoqNhPvtc3g80kcGGUwPuNfNdyP3cZCN3PbiSIqHk9MiJIDiaIrhy1gmrVMGH7ZBb5tRHWJi3-nyAf7nESqXtQBGJINg&access_token=eyJraWQiOiJhV05oNVJJc0NQQXNSWlZJXC9KUUdRcUpcL1wvdnRcL1wvaHl2S203WWxpK0FyYkU9IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiIwNzQ4ZTRlMC0wZTgzLTQ5ZjYtODFkYS1kYzFmNDY4ZTM3ZmQiLCJjb2duaXRvOmdyb3VwcyI6WyJ1cy1lYXN0LTFfUDVmeXVreUMxX0FELU1wdTIwMTcxMiJdLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6Im9wZW5pZCBlbWFpbCIsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX1A1Znl1a3lDMSIsImV4cCI6MTUxMzA4NTM3NCwiaWF0IjoxNTEzMDgxNzc0LCJ2ZXJzaW9uIjoyLCJqdGkiOiIxMWExMjQ2Ny0yMGY2LTQ1YTQtYWFmNi0xZDQyNmQzNjM5ZmQiLCJjbGllbnRfaWQiOiI3aG9zZnBxZGgwMDNxcm5nNGhzdTJpb25qayIsInVzZXJuYW1lIjoiQUQtTXB1MjAxNzEyX21pa2FlbC5wdWl0dGluZW5Ac2M1LmlvIn0.irNfJPGKhcyez6_aEDm_OfUFMOh2oNC9xKTRAM97pvLejVBCrb_mXSMhB2-zzGp_uhH6ayJfwhWOMY2LRjnMa2sm85ExBCI6kw3D3lrViM0LTBPbGC3T6rhneA9lbAL7TRlLoFetp56wK_ojuTZpo-Esm-GlbpNenegZ9T_tL7LZ8xOpq1d25SYRyUUwp1LwajxmPIuzmBMXMw1qoOHt1i4L0IcXNi6HdMO6Z7lejxhRClCZUbE_FXHC9TcR-Bb9yXbxl0PAksHCrf4AQXY9BO_u2oD05OZA5n5r9FPlwHYwHDjYqfGoJ4mY15LAPC7QaIJgLRYPQDfBBVWq4MDH3Q&expires_in=3600&token_type=Bearer

The access token is in JWT format. In the case above, the contents of the token (decoded using https://jwt.io) are:

{
  "sub": "0748e4e0-0e83-49f6-81da-dc1f468e37fd",
  "aud": "7hosfpqdh003qrng4hsu2ionjk",
  "cognito:groups": [
    "us-east-1_P5fyukyC1_AD-Mpu201712"
  ],
  "email_verified": false,
  "identities": [
    {
      "userId": "mikael.puittinen@sc5.io",
      "providerName": "AD-Mpu201712",
      "providerType": "SAML",
      "issuer": "https://sts.windows.net/a9b6726a-6c00-4fd6-aa20-17d7696c954e/",
      "primary": "true",
      "dateCreated": "1513081374954"
    }
  ],
  "token_use": "id",
  "auth_time": 1513081774,
  "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_P5fyukyC1",
  "cognito:username": "AD-Mpu201712_mikael.puittinen@sc5.io",
  "exp": 1513085374,
  "iat": 1513081774,
  "email": "mikael.puittinen@sc5.io"
}

The token also includes a cryptographic signature that should be used to verify its’ authenticity.

 

Additional Sources

More information on the subject is available from e.g.: