We’ve migrated our documentation to a new site, which means some URLs have changed.
Subscriptions

Piano OAuth

Step-by-Step OAuth Instructions

OAuth-1.png

There are four basic steps when working with OAuth (click the diagram above to see a larger version of the OAuth flow). Each of those steps can be broken into two parts, one that requires sending information to Piano's API and a second that involves analyzing Piano's response. This step-by-step guide is intended for anonymous users. For known users, you would skip to step three.

Step 1: Get Code Value

The first step is to get the code value by authenticating the user. To do this you need to first redirect the user from your third-party application to a Piano-hosted page for login/registration. In addition to entering their email and password credentials, for clients using Identity Management social login and passwordless login is also available.

To start the process, you need to generate a link using your OAuth client_id (which is simply your Piano AID) and a redirect URI (which will vary depending on the type of third-party application you're using). The redirect URI is the address where the user will be redirected to after login. On that URI you should expect to receive the code parameter.

Identity Management

https://id.piano.io/id/?response_type=code&client_id=%3CAID%3E&redirect_uri=%3CREDIRECT_URI%3E&disable_sign_up=true

For some third-party applications, one of the OAuth implementation requirements is to disable the ability to create a new Piano user account. To meet this requirement, you can add an additional disable_sign_up parameter to the links you generate. If you need to disable sign up, here is what the links should look like for Identity Management:

Identity Management

 

https://id.piano.io/id/?client_id=<AID>&client_secret=<OAUTH_SECRET_KEY>&redirect_uri=<REDIRECT_URI>&grant_type=authorization_code&code=<CODE>

If you'd like to show the Registration screen instead of the default login screen to your users, please use the screen=register parameter, for example, like shown below:

https://id.piano.io/id/?response_type=code&client_id=<AID>&redirect_uri=%3CREDIRECT_URI%3E&screen=register

After the user has logged in, the user and the code value will be sent to the url specified by the redirect URI.

The base URL for Sandbox is https://sandbox.piano.io/ and all available base URLs for Production are listed here.

Step 2: Get Access Token

Using the code value, you can then request an access token from Piano so the user can be validated by Piano and API requests to Piano can be executed in the name of that user. Piano uses JWT as our token standard, HMAC-SHA256 as our encryption method, and the shared secret as the encryption key.

Here are the parameters you will need to use to get an access token:

client_id

This is your Piano AID.

client_secret

For Identity Management, this OAuth client secret is configured during set-up.

code

This is the code value received in the previous step.

grant_type

You should enter authorization_code as the value for this parameter.

redirect_uri

This is same redirect_uri parameter used in the previous step and you would use the same value as previously.

Using those parameters, here are the API endpoints you should use to make a POST request for Identity Management (US Production):

Identity Management

https://api.piano.io/id/api/v1/identity/token?client_id=<AID>&client_secret=<OAUTH_SECRET_KEY>&redirect_uri=<REDIRECT_URI>&grant_type=authorization_code&code=<CODE>

If the request is successful, the response should look like the following JSON string:

{
    "access_token": "eyJhbGciOiJS...",
    "token_type": "BEARER",
    "refresh_token": "RFbq...",
    "code": 0,
    "expires_in": 36000,
    "ts": 1483536668835,
    "data": {
        "access_token": "eyJhbGciOiJS...",
        "token_type": "Bearer",
        "refresh_token": "RFbq...",
        "expires_in": 36000
    }
}

The base URL for Sandbox is https://sandbox.piano.io/ and all available base URLs for Production are listed here.

You can find an example cURL request for Sandbox below:

curl --location --request POST 'https://sandbox.piano.io/id/api/v1/identity/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<client_ID>' \
--data-urlencode 'client_secret=<SECRET>' \
--data-urlencode 'redirect_uri=http%3A%2F%2Fexample.com' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=<TOKEN>'

When using Identity Linking in a mobile app and calling the /identity/token/validation endpoint from a custom script, you must include the Device-Id header in the request to ensure identity.create events are associated with visitors in Piano Analytics.

On iOS, the device ID can be retrieved using PianoConfiguration.shared.deviceId. On Android, where no public API is currently available, the device ID can be read from SharedPreferences as a workaround. More details are available here.

Step 3: Check Access

Once you have the access token, you can make an API request to Piano to check whether a user should be granted access within a third-party application. Instead of passing the access token as a parameter, you need to make these API requests with an authorization header like this: Authorization: Bearer . To make any consecutive requests, the access_token needs to be saved in the user's session.

To check if the user has access, use your AID and Resource ID with the access check endpoint like so:

GET https://api.piano.io/api/v3/access/check?rid=<RESOURCE_ID>&aid=<AID>
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer <ACCESS_TOKEN>

This request will return the JSON access object similar to this:

{
  "code" : 0,
  "ts" : 1469127375,
  "access" : {
    "access_id" : null,
    "granted" : false,
    "resource" : null,
    "user" : null,
    "expire_date" : 1469127374
  }
}

If user is entitled to access this resource, the “granted” parameter will be set to “true”.

Alternatively, you can get the list of the current access objects using the following method:

https://api.piano.io/api/v3/user/access/list?aid=<AID>

This method will return an array of access objects in the same format as in the previous example and you can check whether the user has access to a resource that grants access. You might want to use this method if multiple resources are able to grant a user access or if you don't want to hard code the Resource ID into the third-party application.

For more information on the methods, you can use for OAuth authentication, see our API documentation on our Access/check endpoint, UserAccess/list endpoint, UserAccess/get endpoint, and the User/get endpoint.

The base URL for Sandbox is https://sandbox.piano.io/ and all available base URLs for Production are listed here.

Step 4: Refresh Access Tokens

Access tokens eventually expire (you can customize the expiration duration when configuring Identity Management) so you'll need to periodically refresh access tokens to ensure that users remain logged in.

To get a new access token, instead of starting the OAuth process from the beginning, you'll use a refresh token to perform a modified version of step two. In addition to those parameters discussed in step two, you'll need to use a refresh_token parameter, which you'll notice was included in the access token response from step two. Note that refresh_token is fixed on initial authentication and not changed upon refresh. You'll also want to set the value of the grant_type parameter to refresh_token.

Here is how you would make a POST request to refresh your access token for Identity Management:

Identity Management

https://id.piano.io/id/api/v1/identity/token?client_id=<AID>&client_secret=<OAUTH_SECRET_KEY>&redirect_uri=<REDIRECT_URI>&grant_type=refresh_token&refresh_token=<REFRESH_TOKEN>

If the request is successful, the response should look like the following JSON string:

{
    "access_token": "eyJhbGci...",
    "token_type": "BEARER",
    "refresh_token": "RFbqr...",
    "code": 0,
    "expires_in": 36000,
    "ts": 1483537155503,
    "data": {
        "access_token": "eyJhbGci...",
        "token_type": "Bearer",
        "refresh_token": "RFbqr...",
        "expires_in": 36000
    }
}

The base URL for Sandbox is https://sandbox.piano.io/ and all available base URLs for Production are listed here.

In addition to refreshing access tokens, you'll want to periodically recheck whether a user should still have access. Rechecking access ensures that users whose subscriptions have lapsed have access revoked across all entitlements. To recheck access, you'll need to repeat the step three process and send a request to the access check endpoint or user access endpoint.

PKCE Support

Our Piano OAuth integration supports the PKCE extension.

The Proof Key for Code Exchange (PKCE) extension describes a technique for public clients to mitigate the threat of having the authorization code intercepted. The technique involves the client first creating a secret, and then using that secret again when exchanging the authorization code for an access token. This way if the code is intercepted, it will not be useful since the token request relies on the initial secret.

If you’d like to apply PKCE to your OAuth flow, you would need to follow the steps described below.

Step 1

Get the OAuth Code using Webform. To do this, you would need to call our API endpoint /id/api/v1/identity/authorize.

GET request example:

https://id.piano.io/id/api/v1/identity/authorize?response_type=code&redirect_uri=&disable_sign_up=false&code_challenge=HbKY_UMqGFHYo6LaGuEo04Nh3fdMcW42y7THv9NooMY&code_challenge_method=S256&client_id=

When successful, you will be redirected to an URL that contains the OAuth code.

For example: https://yourwebsitename.com?code=Mj9smyqVdcqqq2jy

Step 2

Get the Access token via the API endpoint /id/api/v1/identity/token.

Example POST request:

https://id.piano.io/id/api/v1/identity/token

Content-Type: application/x-www-form-urlencoded

Body:

client_id: <AID>
redirect_uri: https://yourwebsitename.com 
grant_type: authorization_code
code: Mj9smyqVdcqqq2jy
code_verifier: h1fvxJZ11lZlka19w445rQqFq0k

Response:

{
"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2lkLnBpYW5vLmlvIiwic3ViIjoiZTAzZDE0NmEtYWE2Yy00MDU1LWFlZmEtOTMzMzUyZDQyYmViIiwiYXVkIjoiUnhscTQyaGlJTCIsImxvZ2luX3RpbWVzdGFtcCI6IjE2MTcwMDgyMjMzMzciLCJlbWFpbCI6InF3ZTJAcXdlLmlvIiwiZW1haWxfY29uZmlybWF0aW9uX3JlcXVpcmVkIjpmYWxzZSwiZXhwIjoxNjE4ODA4MjIzLCJpYXQiOjE2MTcwMDgyMjMsImp0aSI6IlRJdHZvb21DRmFxcXEzaW8ifQ.oO5zKsmma0U4OoRu9B2vGPKPPuCO9--3JOlrcHmWpww",
"token_type": "BEARER",
"refresh_token": "RF52yR53qqq3io",
"code": 0,
"expires_in": 1800000,
"ts": 1617008223338,
"data": {
"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2lkLnBpYW5vLmlvIiwic3ViIjoiZTAzZDE0NmEtYWE2Yy00MDU1LWFlZmEtOTMzMzUyZDQyYmViIiwiYXVkIjoiUnhscTQyaGlJTCIsImxvZ2luX3RpbWVzdGFtcCI6IjE2MTcwMDgyMjMzMzciLCJlbWFpbCI6InF3ZTJAcXdlLmlvIiwiZW1haWxfY29uZmlybWF0aW9uX3JlcXVpcmVkIjpmYWxzZSwiZXhwIjoxNjE4ODA4MjIzLCJpYXQiOjE2MTcwMDgyMjMsImp0aSI6IlRJdHZvb21DRmFxcXEzaW8ifQ.oO5zKsmma0U4OoRu9B2vGPKPPuCO9--3JOlrcHmWpww",
"token_type": "Bearer",
"refresh_token": "RF52yR53qqq3io",
"expires_in": 1800000
}
}

The parameter codeVerifier should be encoded in Base64URLSafe.

For example, using the below JAVA code:

public static void main(String[] args) throws NoSuchAlgorithmException {
    byte[] randomBytes = new byte[20];
    new Random().nextBytes(randomBytes);
    
    String codeVerifier = Base64.encodeBase64URLSafeString(randomBytes);
    
    MessageDigest hash = MessageDigest.getInstance("SHA-256");
    hash.update(randomBytes);
    String codeChallenge = Base64.encodeBase64URLSafeString(hash.digest());
    
    System.out.println(codeVerifier);
    System.out.println(codeChallenge);
}

Step 3

Get the Access token for users using social login.

Example POST request:

https://id.piano.io/id/api/v1/identity/oauth/mobile/token

Content-Type: application/json

Body:

{
"client_id": "<AID>",
"code": "OdkKZwq6o1xu",
"code_verifier": "wIc3UNxl_m3GYEw8UZSD_G0VugvzdWHFhi0c9TDLQMI",
"provider_access_token": "EAAG0YiW2ZCqoBAKuYtTXmkZAODtpLXGlLL1K6cZCwEZChsimrJYNQSvTZCvYXaGnSEPb4fraxC7wJXpc4zBMXrduWr3DyOZABnZAfZCFwbxtMknIZAUxZCDOHIClzUU99vYmLkZAzR8cjV76q3QVdxZBTbM1JW9E4mqhsoWtF0IAjV1OEAZDZD"
}

The parameter provider_access_token is a token from the respective social network (e.g. Facebook, Google, Twitter, LinkedIn).

Response:

Same as in Point 2.

Step 4

Get the Access token just by code or refresh token (without social login)

Example POST request:

https://id.piano.io/id/api/v1/identity/oauth/token

Content-Type: application/json

Body:

{
"client_id": "<AID>",
"refresh_token": null,
"grant_type": "authorization_code",
"code": "SFlBloayUVq7p0nv",
"client_secret": null,
"redirect_uri": "<your_redirect_uri>",
"code_verifier": "wIc3UNxl_m3GYEw8UZSD_G0VugvzdWHFhi0c9TDLQMI"
}

Response:

Same as in Point 2.

Note: In the documentation, steps 2-4 for PKCE are not mandatory or sequential. They are optional components you can use as needed in your implementation.

For more detailed information about the general OAuth flow, you can refer to the section here.

All available base URLs for Production are listed here.

Last updated: