Integrate Azure Active Directory (AD) with AWS Cognito User Pool
Tags: aws, azure, security, beginners
Published: 2020-11-23 10:08:15

Earlier I wrote about [how you can integrate AWS Cognito into your React App](https://dev.to/mubbashir10/implement-auth-in-react-easily-using-aws-cognito-5bhi). In this post, I am going to write down the steps that are needed to use Azure Active Directory (AD) with AWS Cognito as a Federated Identity Provider.

I am assuming you already have setup AWS Cognito User Pool (if not then [read this first](https://dev.to/mubbashir10/implement-auth-in-react-easily-using-aws-cognito-5bhi)) and your Azure Acccount.

#### 1. Create An Enterprise Application
Log in to the [Azure Portal](https://portal.azure.com) and select "Azure Active Directory" from the homepage
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kp3nmiamvhag37kvx80a.png)


From the left side, select "Enterprise applications"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/sec5w3mt3j471f9xyqkr.png)

Click "+ New application"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xzzyxcbpjv8hmbyq9kjz.png)

Select "Amazon Web Services (AWS)"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lewbshf1o993a8gr2a3p.png)

Select "Amazon Web Services (AWS)" again, give any name you would like, click "Create"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gq3ebkkp3opcj9u7dy8u.png)

Once your application has been created, select "Users and groups"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/i64nkpmekm28qtid8veu.png)

Click "+ Add user"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hlyah1zvly92ipeacc7e.png)

Select user/group you want to give access to and click "Select"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/otao9rqiqubj0jc2b8ui.png)

After selecting users/groups, click "Assign"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mh4eaemgg19sgr4pefp0.png)

**ℹ️ Notes**: You can’t add users/groups in your active directory from here, rather this step is to give access to your existing active directory users to the application


#### 2. Setup Single Sign On (SSO)
From the application overview page select "2. Set up single sign on"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/94cteh93erdojjlbpy8i.png)

Select "SAML"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/iru9upzmyk9x3opa72nt.png)

Select "Yes" from the popup (or "No", it really doesn't matter - we will be changing the values eventually)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/w92m3j6x6gnxzpj63bl0.png)

Before proceeding further, we need to set up "Amazon Cognito domain". To do that, go to your AWS Cognito User Pool and from the left sidebar select "Domain name"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/a4yu3wkn39fgk9999sfs.png)

Enter any name you would like to use and click "Save changes" (you may want to check its availability first)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9cfky5wt1no7hlg5tegn.png)

Once the domain name has been set-up. It's time to update SAML configuration from the Azure Active Directory. To do that, click "Edit" from the "Basic SAML Configuration" section
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vwfv5g2nu8twrllhjb7j.png)

Add "Identifier (Entity ID)" and "Reply URL (Assertion Consumer Service URL)", make them default, delete the old values and click "Save"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kgftwz3m7qt1lul1v7xw.png)

Where:

**Identifier (Entity ID):** `urn:amazon:cognito:sp:<user_pool_id>`


**Reply URL (Assertion Consumer Service URL):** `<domain_name_with_full_url_from_the_previous_name>`

You can get the user pool id from the "General settings" tab in the AWS Cognito User Pool
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lxujyf04grbnpluge9q6.png)

Once done, download the "Federation Metadata XML" from the "SAML Signing Certificate" section
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mf1cpim0bo58d4tnx8ci.png)

#### 3. Add Azure Active Directory as a Federated Identity Provider
While being at the AWS Cognito User pool:
- Go to "Identity providers"
- Select "SAML"
- Upload the XML from the previous step
- Give it any name (without spaces)
- Give some description as "Identifiers" (optional)
- Click "Create provider"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vwr57oswnc9m6rqeayw1.png)

After adding Azure Active Directory as Federated Identity Provider (using SAML), you now need to integrate that provider with your app client:

- Go to "App client settings"
- Check the box against your provider name (in my case AzureAD)
- Enter Callback URL(s) - a comma-separated list of URLs to redirect to after login attempt (should be https except for the localhost)
- Enter Sign out URL(s) - this is optional
- Select "Authorization code grant" as the flow type 
- Select "phone, email, openid" as "Allowed OAuth Scopes"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/idh6lonyszrdd9ifsnc0.png)

Read more about the [Authorization Flows and Scopes](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html)

#### 4. Attribute mapping and claims
This is the most confusing but important part of the whole setup. Essentially, you need to map all the attributes that are required in your user pool with your Active Directory.
In my case the only required attribute is "email", to map it:
- Select "Attribute Mapping" from the bottom left
- Click "Add SAML attribute"
- Enter `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email` as "SAML attribute", select `Email` as "User pool attribute" and make sure the capture box is checked
- Click "Save changes"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cd9rfr0kcp90xq68q5fd.png)

**ℹ️ Notes**: Technically you are just mapping the fields from Azure Active Directory with AWS Cognito User Pool's attributes. You can add as many claims as you want and use any name (and namespace) you want. To explain it better I am going to map a claim:

From the Active Directory, select "Edit" under "User Attributes & Claims" section
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kmaz5vqfkratzwqpzzoe.png)

Click "+ Add new claim"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wbqyq2rbzkqi2m16jid7.png)

Give any name, enter anything you like in the namespace, select attribute (or select transformation if you want to transform some field - for example, you want to concatenate first and last name of the Azure Active Directory user) and click "Save"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8002zohpj3pywsu9d4hf.png)

Now map this newly created claim in User Pool to any attribute you want
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/3gm2rtl3g0vcrqwhm7zi.png)

#### 5. Take a test drive
If you don't have any app to handle the callback, you can clone this [simple express server](https://github.com/mubbashir10/express_server) to check the auth response (fail/success)

AWS Cognito provides you a hosted UI using which your users can log in to your app using their Azure Active Directory user account
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/v7u8rbzigbx0q8oe1efh.png)

Click "AzureAD"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/w6ysd6d7gdqtpwkk093s.png)

It will take you to Sign in page
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xtlzql8zbn7aufnsdpef.png)

If successful then it will return you the authorization code, which you need to send to [TOKEN endpoint](https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html) and get the access token
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/3eern6r51agq88bxylhs.png)

It will also create an entry inside the "Users and group" in the Cognito User Pool
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lycbqmd6pcg38l2mxayq.png)

The field/attribute I mapped
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kd1iipk8l4fb0vso37h0.png)

Further Reading:
- [OpenID Claims](https://openid.net/specs/openid-connect-core-1_0.html)
- [Customize AWS Cognito's hosted UI](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-ui-customization.html)