Seamless Azure AD SSO login to React App using Cognito Hosted UI

If you’re looking for a way to use Azure AD as an external identity provider (IDP) to allow single sign-on (SSO) to a React app, you’ve come to the right place.

 

This article will be divided into two parts. In the first part, I will walk you through the process to integrate Azure AD with AWS Cognito. Then, I will walk you through the process of using AWS Cognito Hosted UI with your React app to allow for a seamless SSO login.

Part I

Integrating Azure AD as an external identity provider in AWS Cognito

As shown in the below figure, the high-level application architecture of a serverless app with federated authentication typically involves the following steps:

  1. User selects their preferred IdP to authenticate.
  2. User gets redirected to the federated IdP for login. On successful authentication, the IdP posts back a SAML assertion or token containing the user’s identity details to an Amazon Cognito user pool.
  3. Amazon Cognito user pool issues a set of tokens to the application
  4. Application can use the token issued by the Amazon Cognito user pool for authorised access to APIs protected by Amazon API Gateway.
High-level application architecture of a serverless app with federated authentication in a web or mobile app

Step-by-step instructions for enabling Azure AD as a federated identity provider in an Amazon Cognito user pool

The steps are listed below:

  1. Create an Amazon Cognito user pool
  2. Add Amazon Cognito as an enterprise application in Azure AD
  3. Add Azure AD as SAML identity provider (IDP) in Amazon Cognito
  4. Create an app client and use the newly created SAML IDP for Azure AD

 

Please refer to this AWS Blog Link to perform steps 1 to 4: https://aws.amazon.com/blogs/security/how-to-set-up-amazon-cognito-for-federated-authentication-using-azure-ad/

Note: In the AWS Blog example, when the App client is created they have enabled the OAuth flow flag and set it to “code”. In our example, we will be enabling the OAuth flow flag but will set it to “implicit”.

Since I had issues getting Azure AD set up with Cognito using OAuth flow set to “code”, I have used the “implicit” flag.

If you’re interested, check out this documentation to read more about code flags and how to use them. https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html

Also check the link for available OAuth Flow flags: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpoolclient.html#cfn-cognito-userpoolclient-allowedoauthflows

Part 2

Integrating AWS Cognito Hosted UI with your React App to allow seamless SSO login

Let’s start with a new React project by running the below command.

npx create-react-app sso-react-app && cd sso-react-app

Install Amplify-js by running the below command.

npm install aws-amplify –save

Then import amplify in your App.js.

import Amplify, { Auth } from ‘aws-amplify’

At this stage, we can configure Amplify with the details from our Cognito Pool along with other auth details. I found the best way to achieve this is to break the configuration into two files and import them into the Javascript.

First, create a js file that exports a JSON object.

import config from “./config.json”;

export function getAwsConfig() {
return {
  Auth: {
    region: config.AUTH_REGION,
    userPoolId: config.AUTH_USER_POOL,
    userPoolWebClientId: config.AUTH_CLIENT,
    oauth: {
      domain: config.AUTH_DOMAIN,
      scope: [
        “phone”,
        “email”,
        “profile”,
        “openid”,
        “aws.cognito.signin.user.admin”,
      ],
      redirectSignIn: `${config.SITE_URL}`,
      redirectSignOut: `${config.SITE_URL}`,
      responseType: “token”,
    },
  },
  API: {
    endpoints: [
      {
        name: “API”,
        endpoint: `${config.API_BASE_URL}`,
      },
    ],
  },
};
}
Next create a JSON file named config.json that stores user pool details
{
“SITE_URL”: “http://localhost:3000/”,
“AUTH_REGION”: “ap-southeast-2”,
“AUTH_DOMAIN”: “”,
“AUTH_CLIENT”: “”,
“AUTH_USER_POOL”: “”,
“API_BASE_URL”: “http://localhost:4000/api”
}

It’s worth noting that, in my case, the config file is generated at the time of the app build. It’s recommended not to push your config files to git and good practice to generate your config file at build time.

  • AUTH_DOMAIN is your Hosted UI domain, either the one AWS generated or your custom domain
  • AUTH_CLIENT you can find under App client settings
  • AUTH_USER_POOL you can find under General settings in your Congito User Pool

Import the config to React.

import { getAwsConfig } from “./Config”;

Now we need to configure Amplify to use our configurations. Let’s do this inside the useEffect hook.

import React, { useEffect, useState } from “react”;
import Amplify, { Auth } from “aws-amplify”;
import { getAwsConfig } from “./Config”;

const App = () => {
const [loginStatus, setLoginStatus] = useState(false);

useEffect(() => {
  Amplify.configure(getAwsConfig());

  const checkIfUserLoggedIn = async () => {
    try {
      await Auth.currentAuthenticatedUser();
      return true;
    } catch {
      Auth.federatedSignIn();
      return false;
    }
  };

  checkIfUserLoggedIn().then((data) => setLoginStatus(data));
}, [loginStatus]);

return (
  <div>
    {loginStatus && (<h1> Welcome </h1>)}
  </div>);
}

export default App;

Congratulations! You have just successfully configured Azure AD to act as an IDP and provide SSO to your React App!

Enjoyed this blog?

Share it with your network!

Move faster with confidence