CDSSO Palladium Integration

CDSSO Enables transparent multi-site login for the user using a centralized service that handles Amazon Cognito sessions and sets cookies to the user browser. This document tries to give information about what configurations and changes are needed to do in order to integrate this service. If you have doubts about some terms, jump and read the terms section.

If you need to know last changes in this guide, look at document changelog.

Document Index

  1. Integration guide, an step-by-step guide to integrate this service.
  2. Integration summary and examples.
  3. Glossary of terms.
  4. FAQ

1. Integration guide

There are two steps to integrate the CDSSO in your web application:

  1. Add the CDSSO JS Script in the HTML.
  2. Change the login URLs (Hosted UI/Form/Social auth) and the logout URL of your APP
  3. Implement 2 URLs , login and logout, in your application following the standard Amazon Cognito implementation.

1.1 Integrate the CDSSO at the browser

To integrate the CDSSO with Cognito it's necessary to include the following two <script> tags in the HTML DOM:

JS Script

Add the following script

  <script
      id="cdsso-rewards"
      src="{{ENVIRONMENT_URL}}/js/cdsso.js"
      data-cdsso-url="{{ENVIRONMENT_URL}}"
      data-user-authenticated="{{USER_AUTHENTICATED}}"
      data-redirect-anchor="{{REDIRECT_ANCHOR}}"
      data-login-uri="{{DATA_LOGIN_URI}}"
      data-logout-uri="{{DATA_LOGOUT_URI}}"
      data-redirect-uri="{{DATA_REDIRECT_URI}}" <!-- Optional -->
      data-ajax-logout-uri="{{DATA_AJAX_LOGOUT_URI}}" <!-- Optional -->
      data-ajax-logout-method="{{DATA_AJAX_LOGOUT_METHOD}}" <!-- Optional -->
      crossorigin="anonymous"
  ></script>

and fill the variables that the JS script will use to perform the CDSSO operations:

Live environment example
  <script
    id="cdsso-rewards"
    src="https://api.rewards.aws.palladiumhotelgroup.net/js/cdsso.js"
    data-cdsso-url="https://api.rewards.aws.palladiumhotelgroup.net"
    data-user-authenticated="{{USER_AUTHENTICATED}}"
    data-login-uri="{{DATA_LOGIN_URI}}"
    data-logout-uri="{{DATA_LOGOUT_URI}}"
    data-redirect-uri="{{DATA_REDIRECT_URI}}"
    data-ajax-logout-uri="{{DATA_AJAX_LOGOUT_URI}}"
    data-ajax-logout-method="{{DATA_AJAX_LOGOUT_METHOD}}"
    crossorigin="anonymous"></script>
Staging config example
  <script
    id="cdsso-rewards"
    src="https://api.rewards.stage-eu.aws.palladiumhotelgroup.net/js/cdsso.js"
    data-cdsso-url="https://api.rewards.stage-eu.aws.palladiumhotelgroup.net"
    data-user-authenticated="{{USER_AUTHENTICATED}}"
    data-login-uri="{{DATA_LOGIN_URI}}"
    data-logout-uri="{{DATA_LOGOUT_URI}}"
    data-redirect-uri="{{DATA_REDIRECT_URI}}"
    data-ajax-logout-uri="{{DATA_AJAX_LOGOUT_URI}}"
    data-ajax-logout-method="{{DATA_AJAX_LOGOUT_METHOD}}"
    crossorigin="anonymous"></script>

JS Sentry

This piece of code is for helping us to debug incidents with the library. This can be added to both staging and live environments.

Sentry won't collect user nor web data, only exceptions that occurred in the JS script.

  <script
    src="https://browser.sentry-cdn.com/5.16.1/bundle.min.js"
    integrity="sha384-XeIbINcUQP10HtmVHwZigannjNDpoQRe+uhAoW9J5HU5dHFpilP164LjqO78xtIB"
    crossorigin="anonymous"
  ></script>

1.2 Change the login URLs (Hosted UI/Form/Social auth) and the logout URL of your APP

You need to replace login URLs in your application using cognito Hosted UI, form or social auth.

This screenshot shows the login form inputs. The submit button must send a POST request to the login url: https://{{ENVIROMENT_URL}}/login/form/?login_uri={{DATA_LOGIN_URI}}

First domain

You can see on the screenshot social login buttons (Facebook and Google). These buttons must be configured to open CDSSO configured social auth urls.

1.3 Amazon Cognito authentication in the backend side

You must implement the Amazon Cognito authentication in order to unify and store user data in your own authentication system.

For Django, we modified the library drf-cognito-code-grant to authorize the user after being authenticated via Amazon Cognito with the CDSSO Service:

CDSSO Login and Logout URLs

Your application must implement two endpoints login and logout to handle Cognito authentication tokens. We'll refer to these urls with Auth URLs (See the next section Auth URLs to know how to implement Cognito authentication in the backend side).

The CDSSO Service also implement the Login and Logout urls and they are going to be called by the user to login or logout with Amazon Cognito. The CDSSO Service is going to manage the central auth tokens by itself setting a cookie in the user browser.

To use the CDSSO auth flow. It's important to change your app Login URLs and Logout URL to point directly to the CDSSO Service. These urls are:

There are examples and more detailed explanation in the section below.

Three login methods, Login (Hosted UI) and Login Form (POST Request)

Login (Hosted UI)

Simply a link you can use to redirect the User to the Amazon Cognito Hosted UI to perform the login operation. Example: {{ENVIRONMENT_URL}}/login/

Login Form (POST Request)

With this URL you can send a POST Request using a form or AJAX. The parameters are:

Social Login (Social provider Hosted UI)

Link to CDSSO with the same parameters as Cognito's /oauth2/authorize/:

The redirect_uri GET parameter in /login/ and /login/form/ URLs

Optionally, you can define a redirect_uri GET parameter when setting the LOGIN URL anchor. This behaviour is explained in the JS Script Variables section.

An ajax session logout

Additionally, you can use an alternative logout url if you design a ajax logout in your application.

This, unlike logout url, does not respond with a 302 response redirect but with a json in which its status is reflected. It is the responsibility of your application to close the user's session.

Unified CDSSO Logout

When the /logout URL is called from a website, the cookie will be set as INVALIDATED and when user is going to visit the second web page, if it's authenticated yet, it will be automatically redirected to site logout URL.

Auth URLs

These two URLs are not going to be called by the user directly but from the CDSSO Service.

The app is not going to do any request to Amazon Cognito directly because this is handled by the CDSSO Service. Beside that, the app must implement two urls (login/logout) that handle Cognito authentication with tokens.

LOGIN URL

First domain

The app must have a login URL that receives three JWT tokens as GET parameters from the CDSSO Service:

From this, you have to follow the standard Cognito implementation, validating and decoding these 3 tokens, creating/getting a user and authenticating it in the app.

Step 1

Collect GET parameters: id_token, access_token, refresh_token. Optionally collect redirect_uri.

Step 2

Validate the tokens (you will need the COGNITO_APP_ID here) and decode these 3 JWT tokens. This is the part you have to implement of a standard Cognito implementation.

https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html

For Django, you can use a library that APSL has implemented and published on github: drf-cognito-code-grant.

Step 3

The decoded id_token has an username and an email that you will need to handle the app authentication. Create a new user with the decoded token info or get an existing one from the database.

Authenticate it.

https://docs.aws.amazon.com/cognito/latest/developerguide/scenario-backend.html

Step 4

Make a redirect to the home or profile page with the active user session.

LOGOUT URL

First domain

Your app must call to {{ENVIRONMENT_URL}}/logout of the CDSSO Service to invalidate the session and return the control of the logout endpoint of you app. It will be triggered from the CDSSO Service when the /logout CDSSO URL is called.

How logout does work?

When calling /logout, the CDSSO Service is going to check if the cookie value is in the database and invalidate it. After that, CDSSO Service is going to redirect to the App's logout URL.

When visiting a 2nd domain, the JS's check will receive an invalidated cookie response. If the user is still authenticated in the site, the JS will make a redirect to the App's logout URL. IMPORTANT: This flow is going to happen in every site that integrated the CDSSO Service.

IMPORTANT

To be able to encode and decode the JWT tokens, all the applications implementing the CDSSO must have the same COGNITO APP ID.

Authentication flow

First domain

Hosted UI

First domain

Form POST

First domain

Social Login

First domain

Second domain

Second domain

Summary & Examples

In summary, to integrate you app with CDSSO Service you must add the scripts mentioned above. Implement a login and logout callbacks previously specified and finally make sure the user use the CDSSO Service login and logout endpoints to authenticate and log out respectively.

First domain

Steps to integrate a django app with the CDSSO service.

As explained in point 1 of the current documentation, you add in the "base" template (django template used in all views) the following scripts with the required data:

# base_template.html

  <script
    src="https://browser.sentry-cdn.com/5.16.1/bundle.min.js"
    integrity="sha384-XeIbINcUQP10HtmVHwZigannjNDpoQRe+uhAoW9J5HU5dHFpilP164LjqO78xtIB"
    crossorigin="anonymous"></script>

  <script
    id="cdsso-rewards"
    src="https://api.rewards.stage-eu.aws.palladiumhotelgroup.net/js/cdsso.js"
    data-cdsso-url="https://api.rewards.stage-eu.aws.palladiumhotelgroup.net"
    data-user-authenticated="{{ user.is_authenticated }}"
    data-login-uri="{{DATA_LOGIN_URI}}"
    data-logout-uri="{{DATA_LOGOUT_URI}}"
    crossorigin="anonymous"></script>

Adapt your templates to show that the user is logged in or not (if you have not already implemented it) and you will change the login/logout URLs for authentication to those of the CDSSO service (as indicated in login/logout urls

# menu.html

<li class="login-menu">
  {% if request.user.is_authenticated %}
    <a href="{{ setting.cdsso_logout_url }}">
      <span class="button">
        {% trans 'Log me out' %}
      </span>
    </a>
  {% else %}
    <a href="{{ settings.cdsso_login_url }}">
      <span class="button">
        {% trans 'Log me in' %}
      </span>
    </a>
  {% endif %}
</li>

In addition, you must implement the authentication endpoints for login and logout. You can implement a custom Django Authentication Backend to suit Cognito specifications or you can also use one of the one that APSL has implemented and published on github: drf-cognito-code-grant.

# settings.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'cognito_code_grant.authentication.CognitoAuthentication',
    )
}

LOGIN_URL = "https://api.rewards.stage-eu.aws.palladiumhotelgroup.net/login/"
LOGOUT_URL = "https://api.rewards.stage-eu.aws.palladiumhotelgroup.net/logout/"
# urls.py

# Cognito - only for login.
url(r'auth/', include_auth_urls()),
# Auth - only for logout, login with cognito.
url(r'accounts/', include('django.contrib.auth.urls')),

Finally, you must necessary to provide those responsible for the SSO service with the login and logout callback urls so that the service knows how to manage redirects.

Example of network requests

1st domain: https://ushuaia.staging.k8s.apsl.net/

First domain (App 1 on the previous schema)

2nd domain: Local Django App

Second domain (App 2 on the previous schema)

Glossary of terms

1. What are the callback URLs?

There are two callback URLs. One of them for the login and the other for application logout.

2. What are uls callback for?

The login and logout URLs implemented in your application are used so that the CDSSO service can redirect the response after authenticating against the Cognito service and return the information that allow you identify the user. In this way, the return urls must be in charge of treating the user's data for the purpose of each one.

3. What is the hosted UI?

This represents the endpoint against which the end user will login, the Cognito Service SSO interface:

Hosted UI

FAQ

1. Safari current status
1.1. Why do we use a browser redirect in the first iteration?

Because of ITP 2.3, Safari by default discards cookies set by another domain. This behaviour only happens in normal browsing mode but not in incognito mode. Also, because of Safari behaviour, a control cookie (checksettempcookie) is set in the app domain to avoid infinite redirects.

1.2. Safari infinite redirects workaround

When an user loads a web with implemented CDSSO with Safari this is what happens:

Specification: https://webkit.org/blog/9521/intelligent-tracking-prevention-2-3/

2. How can I test the complete workflow with a 2nd domain?

We have prepared a staging Ushuaia environment with the CDSSO activated in: https://ushuaia.staging.k8s.apsl.net/

3. What is the relationship between the CDSSO service and the AWS Cognito service?

The CDSSO service is a layer of software that is responsible for managing requests from multiple web applications. This service is ahead of the Cognito service and checks if a user X is logged in to a central system, so that if this same user X accesses another application included in the CDSSO, the user authenticates automatically.

See the diagrams:

4. What should we change if we do not want CDSSO authentication?

In this case, you must eliminate the scripts in the application templates and change the login and logout urls that point to the CDSSO service. You must also follow the instructions in the official documentation to integrate the Cognito service. Note: You can keep the implemented callback urls. The managed data of Cognito and CDSSO services are identically.

Document changelog

This changelog will help you to review recent updates on the documentation

Date Change explanation
2020-09-22 Added new second point to implement social auth and login with a form (POST http request).
2020-10-20 Added needed data-login-uri and data-logout-uri parameter to script importation and login/logout URLs.

Contact

Email: PHG support