AMAZON COGNITO SAML FEDERATION WITH UPSSO

Amazon Cognito is a cloud service that provides authentication, authorization, and user management functionalities for your custom web or mobile applications. Amazon Cognito user pools allow sign-in through a third party (federation) SAML IdP(Identity Provider) such as UPSSO.

            This guide provides step by step instructions to setup UPSSO as an Idp for Amazon Cognito user pool through SAML federation. This guide also provides a simple PHP application to demonstrate the sign-in through the SAML federation.

PREREQUISITES

  • Administrator access to the UPSSO portal.
  • Access to the AWS console (https://console.aws.amazon.com/)
  • A PHP web server such as XAMPP to deploy the demo web application.

CREATING AMAZON COGNITO USER POOL AND APP CLIENT

A Cognito user pool manages user data such as username, password, email, phone number, etc. It allows users to sign-in to your web or mobile application through SAML Idp’s such as UPSSO. Here are the instructions for creating a user pool.

  1. Login into AWS console (https://console.aws.amazon.com/)
  2. Go to the Services menu and click on the Cognito link under the “Security, Identity, & Compliance” section.
  3. Click on the “Manage User Pools” button.
  4. Click on the “Create a user pool” button.
  5. Enter a pool name (Ex: DEMO_USER_POOL)
  6. Click on the “Review defaults” button.
  7. Click on the “Edit” button for Required attributes as highlighted below,

8) Make sure email & phone number attributes are selected as shown below,

9) Click on the “Next step” button.

10) Click on the “Review” from the left side of the screen and click on the “Create pool” button.

11) A message will be displayed as “Your user pool was created successfully”. Take a note of the “Pool Id” (Ex: ap-south-1_lE7Nih8bY)

12) Click on the “App clients” link from the left side menu.

13) Click on the “Add an app client” link.

14) Enter the “App client name” (Ex: DEMO_PHP_APPLICATION)

15) Select the other options as shown below,

16) Click on the “Create app client” button.

17) Take a note of the “App client id” displayed (Ex: 2h2pufmdv0524guh86a12j9fds)

OBTAINING UPSSO IDP METADATA

We need to import the UPSSO IDP Metadata XML into AWS Cognito for the SAML federation. Here are the instructions for the same,

  1. Visit the URL, “https://<UPSSO_SERVER_HOST>/upsso/get-idp-metadata” (No username/password required). The metadata XML document will be displayed.
  2. Right-click on the document and select “Save as...” option.
  3. Enter the file name as “upsso_metadata.xml”
  4. Select the “Save as type” as “XML Document”
  5. Click on the “Save” button to download the XML.

CONFIGURING SAML FEDERATION FOR COGNITO USER POOL

  1. Login into AWS Console and open the user pool created above (Ex: DEMO_USER_POOL)
  2. Click on the “Federation” => “Identity Providers” link from the left side menu.
  3. Click on the “SAML” button.
  4. Click on the “Select file” button and select the “upsso_metadata.xml” downloaded above.
  5. Enter “Provider name” as “UPSSO”
  6. Click on the “Create provider” button.
  7. Click on the “Configure attribute mapping” link.
  8. Click on the “Add SAML attribute” link.
  9. Enter “SAML attribute” like “email”.
  10. Select “User pool attribute” as “Email”.
  11. Click on the “Add SAML attribute” link again.
  12. Enter “SAML attribute” like “mobile”.
  13. Select “User pool attribute” as “Phone Number”.
  14. Click on the “Save changes” button.

CONFIGURING DOMAIN NAME

  1. Login into AWS Console and open the user pool created above (Ex: DEMO_USER_POOL)
  2. Click on the “App integration” => “Domain name” link from the left side menu.
  3. Enter a domain prefix (Ex: upsso-saml)
  4. Make sure to check the availability of the domain by clicking on the “Check availability” button.
  5. Click on the “Save Changes” button.

CONFIGURING APP CLIENT SETTINGS

  1. Login into AWS Console and open the user pool created above (Ex: DEMO_USER_POOL)
  2. Click on the “App integration” => “App client settings” link from the left side menu.
  3. Select “UPSSO” under “Enabled Identity Providers”.
  4. Enter the “Callback URL” as “http://localhost/demo_cognito_client_app/secure_page.php” (We will be installing this demo PHP application in a section down below)
  5. Select the “Implicit grant” checkbox under “Allowed OAuth Flows”.
  6. Select the “phone”, “email”, “openid”, “aws.cognito.signin.user.admin” and “profile” checkboxes under “Allowed OAuth Scopes”.
  7. Refer to the screenshot below,

8. Click on the “Save changes” button.

9. Click on the “Launch Hosted UI” button.

10. A new tab will be opened with a Hosted UI URL. Copy the URL in the address bar and keep it for later use in UPSSO.

Example:

https://upsso-saml.auth.ap-south-1.amazoncognito.com/login?client_id=2h2pufmdv0524guh86a12j9fds&response_type=token&scope=phone+email+openid+aws.cognito.signin.user.admin+profile&redirect_uri=http://localhost/demo_cognito_client_app/secure_page.php

CREATING ACCESS KEYS

  1. AWS Access Key & Secret is required to make programmatic calls to AWS services like Cognito. Here are the instructions to generate the same,
  2. Login into AWS Console.
  3. Click on your username available on the top right corner of the page.
  4. Click on the “My Security Credentials”.
  5. Click on the “Create access key” button.
  6. A message will appear as “Your new access key is now available.”
  7. Click on the “Show secret access key” link to display the secret key.
  8. Take a note of the “Access key ID” & “Secret access key” as we need them to be configured in the demo PHP application. (Ex: Access key ID=AKIA4J62PCPJKV5RFT4M, Secret access key=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)

INSTALLING THE DEMO PHP APPLICATION

  1. Install the latest version of XAMPP on a windows box hosted in AWS. (https://www.apachefriends.org/index.html)
  2. Install the latest version of Composer for Windows https://getcomposer.org/
  3. Create a directory “demo_cognito_client_app” under “C:\xampp\htdocs”.
  4. Create a file “composer.json” under “C:\xampp\htdocs\demo_cognito_client_app” directory and copy the following content. (This file has the AWS SDK dependencies)
{
    "require": {
        "aws/aws-sdk-php": "^3.21"
    },
    "autoload": {
        "psr-4": {"AWSCognitoApp\\": "src"}
    }
}

5) Create a file “secure_page.php” under “C:\xampp\htdocs\demo_cognito_client_app” directory and copy the following content.

<?php
namespace AWSCognitoApp;
require_once('vendor/autoload.php');
use Aws\CognitoIdentityProvider\CognitoIdentityProviderClient;
?>


<!DOCTYPE html>
<html>
<head>
	<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;400&display=swap" rel="stylesheet">
	<style>
		body{
			font-family: 'Roboto', sans-serif;
		}
	</style>
</head>
<body>
<h1>DEMO PHP COGNITO CLIENT APPLICATION</h1>


<?php
if(!isset($_GET["access_token"]))
{
	
?>
<script>
	var url_str = window.location.href;
	//On successful authentication, AWS Cognito will redirect to Call-back URL and pass the access_token as a request parameter. 
	//If you notice the URL, a “#” symbol is used to separate the query parameters instead of the “?” symbol. 
	//So we need to replace the “#” with “?” in the URL and call the page again.
	
	if(url_str.includes("#")){
		var url_str_hash_replaced = url_str.replace("#", "?");
		window.location.href = url_str_hash_replaced;
	}
	
</script>

<?php
}
else{
?>

<?php

$access_token = $_GET["access_token"];

$region = 'ap-south-1';
$version = '<AWS_REGION>';

//Authenticate with AWS Acess Key and Secret
$client = new CognitoIdentityProviderClient([
    'version' => $version,
    'region' => $region,
	'credentials' => [
                    'key'    => '<AWS_ACCESS_KEY>',
                    'secret' => '<AWS_SECRET>',
                ],
]);

try {
	//Get the User data by passing the access token received from Cognito
    $result = $client->getUser([
        'AccessToken' => $access_token,
    ]);
	
	//print_r($result);
	
	$user_email = "";
	$user_phone_number = "";
		
	//Iterate all the user attributes and get email and phone number
	$userAttributesArray = $result["UserAttributes"];
	foreach ($userAttributesArray as $key => $val) {
		if($val["Name"] == "email"){
			$user_email = $val["Value"];
		}
		if($val["Name"] == "phone_number"){
			$user_phone_number = $val["Value"];
		}
	}	
	echo '<h2>Logged-In User Attributes</h2>';
	echo '<p>User E-Mail : ' . $user_email . '</p>';
	echo '<p>User Phone Number : ' . $user_phone_number . '</p>';
	echo "<a href='secure_page.php?logout=true&access_token=$access_token'>SIGN OUT</a>";
	
	if(isset($_GET["logout"]) && $_GET["logout"] == 'true'){
		//This will invalidate the access token
		$result = $client->globalSignOut([
			'AccessToken' => $access_token,
		]);
		
		header("Location: <COGNITO_HOSTED_UI_URL>");
		
	}
	
	
} catch (\Aws\CognitoIdentityProvider\Exception\CognitoIdentityProviderException $e) {
    echo 'FAILED TO VALIDATE THE ACCESS TOKEN. ERROR = ' . $e->getMessage();
	}
catch (\Aws\Exception\CredentialsException $e) {
    echo 'FAILED TO AUTHENTICATE AWS KEY AND SECRET. ERROR = ' . $e->getMessage();
	}

}
?>

</body>
</html>


6) Replace the following in the above source code,

<AWS_REGION> = Region string AWS instance (For example: ap-south-1)

<AWS_ACCESS_KEY> = Access key generated in “CREATING ACCESS KEYS” section above (For example AKIA4J62PCPJKV5RFT4M)

<AWS_SECRET> = Secret generated in “CREATING ACCESS KEYS” section above (For example BfAiu3tpMQXQiUHb9cNqXV4Xo/iVbTV6E0BzI6XT)

<COGNITO_HOSTED_UI_URL> = The Hosted UI URL captured at the “CONFIGURING APP CLIENT SETTINGS” section above. (For example, https://upsso-saml.auth.ap-south-1.amazoncognito.com/login?client_id=2h2pufmdv0524guh86a12j9fds&response_type=token&scope=phone+email+openid+aws.cognito.signin.user.admin+profile&redirect_uri=http://localhost/demo_cognito_client_app/secure_page.php)

7) Save the close the file.

8) Open the command prompt and go to the directory “C:\xampp\htdocs\demo_cognito_client_app”.

9) Execute the following command to install the dependencies,

composer install

10) Start the Apache server from the XAMPP control panel.

CONFIGURING AMAZON COGNITO IN UPSSO SAML

  1. Login into the UPSSO portal as an admin user.
  2. Click on the “Application Management” from the left side menu.
  3. Click on the plus button to add a new application.
  4. Click on the “ADD NEW APP” icon.
  5. Enter Name as “AWS COGNITO”.
  6. Enter EntityID as per the format below. Replace <USER_POOL_ID> id with the user pool id noted above.
urn:amazon:cognito:sp:<USER_POOL_ID>

For example:

urn:amazon:cognito:sp:ap-south-1_lE7Nih8bY

7. Enter “AssertionConsumerService” as per the format below. Replace <COGNITO_DOMAIN> with the domain configured above in the “CONFIGURING DOMAIN NAME” section.

<COGNITO_DOMAIN>/saml2/idpresponse

For example:

https://upsso-saml.auth.ap-south-1.amazoncognito.com/saml2/idpresponse

8. Enter “NameIDFormat” as “urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified”.

9. Enter “NameIDAttribute” like “email”.

10. Select “supp_only_sp_to_idp” checkbox.

11. Enter “sp_origin_url” as the Hosted UI URL copied in the “CONFIGURING APP CLIENT SETTINGS” section.

Example:

https://upsso-saml.auth.ap-south-1.amazoncognito.com/login?client_id=2h2pufmdv0524guh86a12j9fds&response_type=token&scope=phone+email+openid+aws.cognito.signin.user.admin+profile&redirect_uri=http://localhost/demo_cognito_client_app/secure_page.php

12. Click on the “SAVE” button.

13. Refer to the following screenshot for reference,

TESTING THE COGNITO SAML FEDERATION

  1. Login into the UPSSO portal as a user.
  2. Click on the “AWS COGNITO ” icon.

3. Click on “UPSSO” button as shown below,

4. Enter the OTP.

5. The user will be logged in to the demo PHP application. The application will retrieve the user attributes from the AWS User Pool and display it to the user.