Authentication and User Identification

This article includes code samples. If you would like to see them for a specific language, select a language now.

Most calls to the Moonsense APIs require authentication in order to process the requests. Authentication is mainly handled through the use of a Bearer provided via the Authentication Header and the level of user identification depends on the type of token provided to the Moonsense API.

Types of tokens

There are 3 types of tokens used to authenticate with the Moonsense API. These tokens are always tied to a specific application and developers can use the Moonsense Console to generate two of the three tokens listed below, namely the Public Token and the Secret Token.

Public Token

This token is the most restrictive of the three tokens. This token can be generated by accessing a specific application in the Moonsense Console. This token is provided to the Moonsense API as a part of an upgrade process to generate an App Access Token. Developers can also perform this upgrade using their own custom endpoint implementation(more on that later). When using a Public Token, developers can also provide an optional user identification to associate the token with a user performing the request.

App Access Token

As the name suggests, this is the primary token that is used by most Moonsense API endpoints. These tokens are usually short lived and need to be regenerated on expiry. These tokens are only available via an endpoint upgrade process and cannot be generated via the Moonsense Console. All SDKs provide a default implementation that performs this upgrade using the Public Token provided via the initialization routine. These tokens have ingest permissions that allow the caller to write to the Moonsense backend. By default the App Access Token generated by the SDK expire every 24 hours. In most cases, developers do not have to concern themselves with this nuance as the SDK does the work of requesting for a new token on expiry. However, in the case of a custom implementation it is the responsibility of the developer to request for a new App Access Token whenever the old one expires.

Secret Token

This is the most permissive of the three tokens. When generating tokens via the Moonsense Console, the Secret Token is only available at the time of creation. It is therefore the responsibility of the developer to hold on to this token past this point(the Public Token however can be retrieved at any point post creation). The Secret Token is usually used as a part of a consumption flow allowing the developer to access all the data that has been reported to an application via the ingest mechanism. These tokens do not provide any user identification and therefore should not be used from an ingest standpoint.

Creating tokens via the Console

Once logged in to the Moonsense Console. Click on the Apps tab in the left panel to view all Apps available to the developer.

List all apps

Next, select the app you want to generate tokens for and click the Create token button.

Create a token

Provide a name for the token.

Name a token

And finally acknowledge that you have copied over the tokens.

View tokens

Default App Authentication

The SDK automatically handles the process of upgrading your Public Token into an App Access Token using the value for the Public Token that is passed into the SDK initialization process. This App Access Token is then used to make authenticated requests to the Moonsense API. By default, no user information is associated with the token and the userId and clientUserId associated with the bundles will be blank.

User Association

There are two methods to associate a User with the Session being tracked. Each method is specified in a separate field to make it easy to distinguish which method was used. The first field is clientUserId. The second is userId. They have separate levels of complexity and meaning, which are described in the following sections.

clientUserId Field

The simplest method of user association is to provide the SDK with a clientUserId through the SDK's setClientUserId method. This clientUserId can be set to anything and is specified by the implementing code. There is no validation that comes with this clientUserId outside of any done by the implementing application. It is also subject to change during a Session. This method is useful when you don't want to perform any validation on your backend and strict user information is not required.

userId Field

The userId method requires you to implement a custom token upgrade handler in both the app and on your backend. This method replaces the default token upgrade process used by the Moonsense SDK with a custom one that requires that the requesting user passes authentication within your own backend. Setup of the Custom Token Upgrade Handler is detailed below. Setup of the backend token upgrade process is detailed in the Custom Backend Token Upgrade section below.

Once implemented, the Bundles will include a userId field. This userId is definitively associated with the user specified and has passed authentication within your own backend implementation.

Custom Token Upgrade Handler

Implementing a tokenUpgradeHandler is necessary to tell the SDK how to fetch a token from your Custom Backend Token Upgrade endpoint. It is required if you want your backend to create a token with a validated userId. This handler is then passed to the Moonsense SDK on initialization.

The Handler

The handler setup will vary slightly by platform but all platforms follow the same approach.

The handler will be passed the publicToken that is given to the Moonsense SDK on initialization. The handler is then expected to return a appAccessToken to the Moonsense SDK. The expectation inside this handler is that your application will use any state information you have to communicate with your own Custom Backend Token Upgrade endpoint to fetch the appAccessToken.

Example Handler

Below is a template of what a Custom Token Upgrade Handler can look like

/** * The custom token upgrade handler implements the `TokenUpgradeHandler` interface. * The `requestNewToken` method takes the public key as an argument and a onComplete * function type which returns the upgraded `appAccessToken` or an onError function type * for errors. */ val tokenUpgradeHandler = object : TokenUpgradeHandler { override fun requestNewToken( publicToken: String, onComplete: (String) -> Unit, onError: (Exception) -> Unit ) { /** * Perform a network request to the custom token upgrade endpoint, * providing any relevant information required by the back end and * invoke the onComplete function type. */ ... onComplete.invoke(appAccessToken) } } // Provide the token upgrade handler on SDK initialization Moonsense.initialize( context = this, publicToken = "ADD PUBLIC TOKEN HERE ..", tokenUpgradeHandler = tokenUpgradeHandler )
import MoonsenseSDK // The custom token upgrade handler implements the `TokenUpgradeHandler` protocol. // The `requestNewToken` method takes the public key as an argument and a completion // handler which returns the upgraded `appAccessToken` or an error. class CustomTokenUpgradeHandler: TokenUpgradeHandler { func requestNewToken(publicToken: String, _ completion: @escaping TokenUpgradeCompletionHandler) { // Perform a network request to the custom token upgrade endpoint, // providing any relevant information required by the back end and // invoke the completion handler. ... completion(appAccessToken, nil) } } ... // Provide the token upgrade handler on SDK initialization let customTokenUpgradeHandler = CustomTokenUpgradeHandler() Moonsense.initialize(publicToken: <YOUR_PUBLIC_TOKEN_HERE>, tokenUpgradeHandler: customTokenUpgradeHandler, delegate: self) ...
/** * The custom token upgrade handler should take the public key as * an argument and return a Promise that resolves to a string * that represents the `appAccessToken` **/ const customTokenUpgradeHandler = (publicToken) => { // This assumes a response that is of the format: // { "appAccessToken": "<moonsense app access token>" } return fetch('https://example.com/moonsense-token-upgrade') .then(response => response.appAccessToken); } // Create the config object to pass to the Moonsense SDK const moonsenseConfig = { // ...other settings tokenUpgradeHandler: customTokenUpgradeHandler } // Initialize the SDK const moonsenseSdk = Moonsense.init(moonsenseConfig);

Custom Backend Token Upgrade

Implementing a Custom Backend Token Upgrade provides the most assured method of associating a specific user with a session as it requires authentication against your own backend. This method is not required to use the SDK.

The Process

The goal is to obtain an App Access Token that contains a validated userId that can then be used by the SDK on Moonsense API requests. This is accomplished by adding a token request method within your own servers to fetch the token. Requests to this method will perform the following:

  1. Validate the user request
    • Information to this request is passed by the Custom Token Handler from your own app.
  2. Request an App Access Token from Moonsense
    • The request should be sent to api.moonsense.cloud/v2/tokens/upgrade
    • The request should include the header Authentication: Bearer <your secret token>
    • The request body should look as follows: { "public_token": "<your app public token>", "user_id": "<your authenticated user id>" }
  3. Return the created appAccessToken from the Moonsense API request for processing by your Custom Token Handler