Link a partner application to ExorLive with JWT

ExorLive would like to make the process of making a link with partner applications as straightforward as possible. Therefore, ExorLive deals internally with the complicated logic of identify, creating, and authenticating users.

Requirements

  • The partner application is web based or is able to open and view webpages.
  • The partner has a globally unique ID for users and members/patients.
  • The partner application is able to sign the request (the data sent to ExorLive) as a signed JSON Web Token (JWT)

Introduction

This document describes a one way link where the user is logged in to the partner application and has a member/patient/client in focus. The user then clicks the "ExorLive" menu option opening ExorLive in a single sign on manner, after which the member/patient/client is transferred to ExorLive and is set in focus in the ExorLive user interface.

The partner application makes a POST call with all the necessary information to an ExorLive endpoint. This call must include a signed JWT so ExorLive can verify the request. ExorLive responds with a web page.

Usage

The JWT link can be used for two main scenarios:

  1. Linking partner web application to ExorLive Main - integration for instructors.
    Behavior:
    The first time ExorLive sees this user they will be prompted to log in. The next time it will be a single-sign-on. After the user has logged in the ExorLive webpage is displayed logged in and the member/patient is in focus.
  2. Linking partner's mobile application to ExorLive Go - integration for member/patient/client.
    It is recommended to use this as an extension of the integration with ExorLive Main, not as an independent integration.
    Behavior:
    The member/patient/client will be automatically signed in to the ExorLive Go.
    If the member/patient/client has workout plans prepared for them in ExorLive, they will be able to access them.
    If there is no matching account found in ExorLive, a new one will be created.

Request payload

ExorLive can customize the response according to your needs. To get you started we need the following information for the ExorLive Main link:

  • The name and ID* of the organization. ExorLive needs to know which center/clinic/location the call is coming from, this is what we call an "Organization".
  • The name and ID* of the logged in user (instructor).
  • The name and ID* of the contact/client/patient.

Or the following for the ExorLive Go link:

  • The name and ID* of the organization. ExorLive needs to know which center/clinic/location the call is coming from, this is what we call an "Organization".
  • The name and ID* of the contact/client/patient.

*ID refers to globally unique IDs from the partner application. ExorLive strongly prefers using SSN for the contact/client/patient, this way it is easier to identify the contact if they were to log in to "ExorLive GO" with Bank ID.

Any extra user data you provide us with will help us improve the user experience (prefilling of emails etc.).

Example payload for ExorLive Main:

			
{
	"employeeId": "2f3fb098",
	"employeeUsername": "mando",
	"employeeFirstname": "Mando",
	"employeeLastname": "Lorian",
	"employeeEmail": "mando@tatooine.com",
	"organizationName": "Tatooine",
	"organizationId": "ace615c2",
	"contact": {
		"id": "2f3fb098",
		"birthdate": "1969-11-13",
		"ssn": "13116900216",
		"gender": "male",
		"firstname": "Baby",
		"middlename": "",
		"lastname": "Yoda",
		"mobile": "99900000",
		"email": "babyyoda@galaxy.com",
		"diagnosis": "L02",
	}
}
			
		

Example payload for ExorLive Go:

			
{
	"organizationName": "Tatooine",
	"organizationId": "ace615c2",
	"contact": {
		"id": "2f3fb098",
		"birthdate": "1969-11-13",
		"ssn": "13116900216",
		"gender": "male",
		"firstname": "Baby",
		"middlename": "",
		"lastname": "Yoda",
		"mobile": "99900000",
		"email": "babyyoda@galaxy.com",
	}
}
			
		

Security

To verify the request, it must be sent as a signed JSON Web Token (JWT).
The token must be signed using an asymmetric algorithm, which means that there are two keys: one public key and one private key that must be kept secret. We accept the following algorithms: RS256, PS256, ES256. The public key should be shared in jwks.json file hosted at a trusted location (“kid” header required) or using secure procedure agreed upon with ExorLive. Symmetric algorithms like HS256 which use single private key shared between the parties are not accepted. This is due to high risk of compromising the private key as well as its vulnerability to brute force attacks.
Furthermore, we require each token to have typ header with value "JWT" as well as the following claims:

  • exp - expiration time which should not be longer than 5 minutes
  • nbf - not before time which should be equal to the issued time
  • aud - audience with agreed upon value
  • iss - issuer with agreed upon value
  • nonce - uniqe string generated using a cryptographically secure random number generator

JWT sample

Here is a sample JWT with all the security features and payload for instructor.
For creating and signing the JWTs we recommend using an established library, for example for .NET projects you could use jose-jwt which is well documented here.

The POST-call

You send a http POST call which must include a JWT-encoded payload. There are two possible approaches to send the POST call:

  • The preferred method:
    The partner application sends an POST request with the payload as data. ExorLive will return a URL which the partner application opens in the preferred way.
  • The frontend-only approach:
    The partner application opens a new webpage (in a tab, iframe or webcontrol). In that webpage a form POST is sent to ExorLive and ExorLive will return the content to display in that webpage. The form POST call contains one field called "payload".

Code examples:


Curl
  • The preferred method:
    		
    			curl --location --request POST 'https://sso.exorlive.com/partner/partnername/url' \
    			--header 'Content-Type: text/plain' \
    			--data-raw 'eyJ0eXAiOiJK...JIOq1X1-gLo'
    		
    		
  • The forntend-only approach:
    		
    			curl --location --request POST 'https://sso.exorlive.com/partner/partnername/payload' \
    			--header 'content-type: application/x-www-form-urlencoded' \
    			--header 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' \
    			--data-urlencode 'payload=eyJraWQiOiIxMzI5ODc5NTg0M...JvTTUSMmtA-caZ7wFPd_A'
    		
    		
Form POST request in C#

[Route("example/sampledata")]
[HttpGet]
public string GetExamplePayload()
{
    var payload = new
    {
        organizationId = "ace615c2",
        organizationName = "Tatooine",
        employeeId = "2f3fb098",
        employeeUsername = "mando",
        employeeFirstname = "Mando",
        employeeLastname = "Lorian",
        employeeEmail = "mando@tatooine.com",
        contact = new
        {
            id = "2f3fb098",
            birthdate = "1969-11-13",
            ssn = "13116900216",
            gender = "male",
            firstname = "Baby",
            middlename = "",
            lastname = "Yoda",
            mobile = "99900000",
            email = "babyyoda@galaxy.com"
        }
    };
    // Encode the payload as a signed JSON Web Token (JWT).
    string encodedPayload = EncodeJwt(GetSecurityKey(), payload);
    return encodedPayload;
}

Form POST request in JS

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
  <title>ExorLive Partner POST sample</title>
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <script>
    function CallExorLive() {
    	$.ajax({
    		method: "GET",
    		url: "/example/sampledata",
    		cache: false
    	}).done(function (encodedPayload) {
    		var url = "/example/payload";
    		PostSubmit(url, encodedPayload);
    	});
    }
    
    // Do a form POST submit and open a new window with the resulting webpage.
    // Must use FORM SUBMIT instead of AJAX because the result shall be a 
    // new webpage to be opened.
    // This sample will open the resulting webpage in a new tab in the browser.
    //
    // This method based on:
    // https://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit
    // https://stackoverflow.com/questions/178964/after-submitting-a-post-form-open-a-new-window-showing-the-result
    
    function PostSubmit(url, data) {
    	var form = $('<form id="formb" target="_blank"></form>');
    	form.attr("method", "post");
    	form.attr("action", url);
    	var field = $('<input />');
    	field.attr("type", "hidden");
    	field.attr("name", "payload");
    	field.attr("value", data);
    	form.append(field);
    	$(document.body).append(form);
    	form.submit();
    }
  </script>
 </head>
<body>
 <h1>ExorLive Partner POST sample</h1>
 <button onclick="CallExorLive();">Send POST data to ExorLive</button>
</body>
</html>