App Authentication

Note: This guide is a conceptual overview of how Symphony performs secure app authentication. While you can implement the following workflow on your own, the BDK (Bot Developer Kit) provides an out of the box implementation of app authentication making it easy to get started building authenticated apps.

In order to create a secure connection between your app and the Symphony client, apps need to perform app authentication. Upon successful authentication, Symphony extension apps establish a bidirectional trust, allowing for secure and authorized access to user data by leveraging the Symphony Extension API.

In order to perform app authentication, your app must perform a combination of frontend and backend authentication calls to the Symphony client and pod respectively. The following steps provide an overview of the frontend and backend calls your App needs to make:

Note: Many Extension Apps' backend take the form of Symphony bots. The implementation of app authentication provided out of the box by the BDK (Bot Developer Kit) leverages this architectural design.

1. Initialize your Extension App

The first step of app authentication is a frontend call that leverages the Symphony Extension API to initialize your app. This should be used to initialize the connection to the Client Extension API from your application controller:

SYMPHONY.remote.hello()

Note: Each extension app will contain a unique app id that is registered on the Pod. You can learn more about this along with other setup prerequisites in the App Configuration section.

2. Initiate Backend Authentication

The next step of app authentication is to perform a backend authentication call to the authentication endpoint on the pod:

RSA App Authenticate

POST https://<host>:<port>/login/v1/pubkey/app/authenticate/extensionApp

Authenticate your Extension App with an App Token

Request Body

{
  "appId": "appId",
  "appToken": "Ta",
  "symphonyToken": "Ts",
  "expireAt": "<Unix Timestamp in milliseconds of Symphony token expiration>"
}

Your backend should store this token pair as they will be used for subsequent validation steps in the following authentication process.

3. Register your App

The next step of the authentication workflow is to register your app on the Symphony client using the Symphony Extension API. Registering your app requires the following frontend call to be performed in your application controller:

SYMPHONY.application.register(appData, servicesWanted, servicesSent)

Response:

4. Validate Tokens returned by Symphony Frontend

The next step in the authentication workflow is to:

  • validate the App Token JWT returned from the backend API call in step 2

  • validate the Symphony JWT Token that was passed to you through the frontend against the JWT Symphony JWT Token previously attained from executing the backend API call shown in step 2.

While the implementation of this token validation is up to the developer, a sample implementation of both app token and symphony token validation is provided out of the box by the BDK. In this sample implementation, the app frontend sends both the App Token and Symphony Token to the backend where it verifies that the token pair exists in the token cache.

At this point, your app is fully authenticated and has established a bi-directional trust between itself and the Symphony client.

5. Obtain User Identity

Once you have successfully authenticated and validated your tokens, you can obtain user data through the Extension API:

The Extension API provides an extended-user-info service that contains a getJwt() method. In order to leverage this method, your app must first subscribe to the extended-user-info service:

const extendedUserInfoService = SYMPHONY.services.subscribe(
    'extended-user-info',
  );

Once subscribed, you app can leverage the getJwt() method as follows:

extendedUserInfoService.getJwt()

Deprecated Field

The username field has been changed in version 1.55.3, it now returns <email address> instead of <Symphony username>. Please note that this change has been done to help the transition for Applications that were relying on the username field and that the username field will be entirely removed in an upcoming version.

This method returns a base-64 encoded JWT token for the user in context, containing the following data when decoded:

{
    "aud" : "<id of app>",
    "iss" : "Symphony Communication Services LLC.",
    "sub" : "<Symphony user ID>",
    "exp" : "<expiration date in millis>",
    "user" : {
        "id" : "<Symphony user ID>",
        "emailAddress" : "<email address>",
        "username" : "<email address>",
        "firstName" : "<first name>",
        "lastName" : "<last name>",
        "displayName" : "<display name>",
        "title" : "<title>",
        "company" : "<company>",
        "companyId" : "<company (pod) ID>",
        "location" : "<location>",
        "avatarUrl" : "<URL for user's avatar>",
        "avatarSmallUrl" : "<URL for user's small avatar>"
    }
}

At this point, your authenticated app has access to sensitive user data such as the Symphony user ID, username, email address, displayName, company, location, etc. Extension apps can leverage this user data in order to create user-specific workflows and automations.

Known Issue

Currently, calling getJwt() without having completed the application authentication sequence will return Undefined. We will be addressing this in an upcoming release so that userReferenceId will correctly be returned if application authentication has not been completed. In the interim, userReferenceId can still be obtained from the Register and Connect methods.

6. OBO Authentication

If you wish to take this a step further, your app can take the JWT returned in the last step and perform authentication on behalf of (OBO) the user in context. If you wish you learn more about OBO authentication and OBO enabled workflows, continue here:

Next Steps

To learn how to properly configure and authenticate your extension app using the BDK, complete the following configuration tutorial:

Last updated