---
title: "Authentication in Customer&#x27;s Canvas Hub | Customer&#x27;s Canvas Hub"
canonical: "https://customerscanvas.com/docs/hub/dev-center/api/auth/"
---

# Authentication in Customer's Canvas Hub

> In this guide, we'll dive into how authentication works within the Customer's Canvas API. A solid understanding of this process is crucial for the protection and security of both your valuable Customer's Canvas data and your users' confidential order information.

## Supported Auth schemes

Customer's Canvas implements OAuth2 authentication. It supports three OAuth2 flows: 

- Client Credentials Flow
- Implicit Flow
- Authorization Code Flow

## How to register your app in Customer's Canvas Hub

Before you can start using API in your app, you need to register your app in your Customer's Canvas account. Here you choose your preferred OAuth2 flow and get the credentials. 

To register an app, follow these steps:

1. Go to your Customer's Canvas account.
2. Navigate to **Settings** > **External apps**.
3. Click **Create**.
4. Specify your app name. 

   :::tip
   Avoid generic names like **My app** or **Test**. Instead, name it in the same way as you call your app internally. Otherwise, it may lead to confusion.
   :::

5. Choose the preferred auth type (OAuth2 flow). See some guidelines on how to choose it in the next section.
6. Fill in the necessary fields (they vary depending on the auth type - see further explanations). 
7. Copy the Client Id and Secret. You need to use this data in your code.
8. Click **Save**.

### Choosing an Authentication Type

Deciding which authentication scheme to use can be challenging. Here are some suggestions to help you choose the right one for your needs.

#### Client Credentials

Choose this authentication scheme if:

* You need backend-to-backend communication between your app and Customer's Canvas.
* You don't want a Customer's Canvas login screen to appear during authorization.
* You can securely add app credentials to your app configuration, and they are not accessible to unauthorized personnel.

#### Implicit

Choose this authentication scheme if:

* You're making API calls from your browser-based frontend or mobile application.
* You need a Customer's Canvas login screen to appear during authorization, and the API calls should be made on behalf of a signed-in user.
* You don't have a server application that could be used as a proxy for this API.

:::note
If possible, you should consider making API calls from your backend app instead of a frontend app for better security. Use Implicit only if creating a backend app is not an option.
:::

#### Authorization Code

Choose this authentication scheme if:

1. You're making API calls from your server-side backend app.
2. You need a Customer's Canvas login screen to appear during authorization, and the API calls should be made on behalf of a signed-in user.

### Token lifetime

This parameter refers to how long the access token remains valid. The default value is 3600 seconds (1 hour).

It's recommended to keep the token lifetime as short as possible for security reasons. If you request a new token before each API call, you can use a shorter lifetime, such as a few minutes. However, if that's not convenient and you prefer to capture a token on app launch, you can increase the lifetime depending on the length of an app session.

If you're not sure which value to set, it's best to leave the default value of 3600 seconds.

### Permissions

When your app accesses Customer's Canvas resources using the Client Credentials Flow, it does so on behalf of a tenant admin. To protect your resources in case the access token is leaked, it's recommended that you restrict your app's access to only the necessary resources.

You can achieve this by using Permissions (also known as _scopes_). For each resource type, you can decide whether to prevent any access (No Access), allow only read access (Read), allow both read and update access (Update), or allow all CRUD (Create, Read, Update, Delete) operations (Full).

For the Implicit and Authorization Code flows, the Permissions block is disabled. The reason is that, for these flows, the app works on behalf of a user who signed in. The app can do whatever these users are allowed to. 

### Redirect Settings

When using the Implicit or Authorization Code flow in OAuth2, it's necessary to configure additional parameters such as redirect URLs. To understand how to fill them, let's briefly review how these flows work:

1. To authenticate, you make an API call to a special authorize endpoint.
2. As part of the data you send to this endpoint, you specify the _redirect URL_ of your app.
3. The user is redirected from your app to Customer's Canvas login page.
4. Once the user successfully signs in, they are redirected back to the redirect URL specified in Step 2. The access token is included in the query string parameters of the redirect URL.

:::note
This process will be explained in more detail later.
:::

To enhance security and prevent malicious users from receiving access tokens to their apps, it is required to add the same redirect URL (or multiple URLs if you have different implementations of the authentication process) to these settings. You can think of it as a whitelist of redirect URLs.

The same idea is behind the post logout redirect URLs, which are supposed to handle the sign-out process of a user.

You may be concerned about the potential Cross-Origin Resource Sharing (CORS) issues. To avoid them, you should also include the base URL of all your redirect and post-logout endpoints in the **Allowed CORS origins** field.

Here's an example of how to configure these settings: 

- **Redirect URIs**: https://example.com/api/cc-auth/login-callback
- **Post logout redirect URIs**: https://example.com/api/cc-auth/logout-callback
- **Allowed CORS origins**: https://example.com

### Require client secret

This toggle determines whether the app must always send the client secret to the authorize endpoint. Enabling it provides an extra layer of protection against unauthorized access by malicious apps. However, for the Implicit flow, the client secret needs to be exposed on the frontend, making it easier to find. 

Hence, we recommend turning it off for Implicit flow, but always enabling it for the Authorization Code flow.

### Require PKCE

The PKCE (Proof Key for Code Exchange) parameter is a security feature used in the OAuth2 Authorization Code flow to prevent authorization code interception attacks.

When you toggle it on, the app is required to provide additional data to the authorize endpoint to verify its identity. This feature enhances security and should be enabled in the production version of your app. However, you may temporarily turn it off during troubleshooting or when creating a proof-of-concept of your app.

### Revoke Credentials

To revoke the credentials, just remove the External App and create a new one with the same settings. Old Client ID and Client Secret won't be accepted by Customer's Canvas anymore.

## Add credentials to your code

After registering your app as explained above, you'll need to add the Client ID and Client Secret of your External App to your application. This can be done through the app configuration settings or environment variables, depending on your app technology.

Although this may seem like a simple task, it's essential to keep in mind that these credentials provide access to your Customer's Canvas resources and personalization data. Therefore, it's crucial to follow these guidelines:

1. Never hardcode these credentials in your code.
2. Never commit config or .env files containing these credentials under version control system.
3. If you accidentally do so, revoke the credentials and create new ones.
4. For .NET developers working in a development environment, we recommend passing these parameters to the configuration using the dotnet user-secrets command, as explained in the  [Safe storage of app secrets in development in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-7.0&tabs=windows) article in Microsoft documentation. Use similar mechanisms for other platforms if possible.
5. For production environments, consider using secret management solutions like Azure KeyVault, AWS Secret Manager, AWS System Manager Parameter Store, HashiCorp Vault, or similar systems.

By following these guidelines, you can help protect Customer's Canvas credentials from unauthorized access.

## Authentication API

Customer's Canvas offers an OAuth2-compatible authentication API with the same base address used for the Customer's Canvas admin panel, depending on your instance:

- For the US environment: https://customerscanvashub.com
- For the EU environment: https://eu.customerscanvashub.com
- For the AU environment: https://au.customerscanvashub.com

To implement a standard OAuth2 authorization scenario, you'll need to work with the following main endpoints:

- Get a discovery document endpoint (information about other API endpoints)
- Authorize endpoint
- Token request endpoint
- End session endpoint

While there are additional endpoints available, these four are enough to implement a basic scenario. 

The goal of using this API is to obtain an _access token_, which should be included with all requests to Customer's Canvas APIs, as explained further.

Note that the authentication API is not covered by Swagger, so there are no official API clients available. You'll need to either make HTTP calls directly or find a third-party library to handle OAuth2 authentication. For example, for .NET applications, you can use the [IdentityModel library](https://www.nuget.org/packages/IdentityModel/) (see the [docs](https://identitymodel.readthedocs.io/en/latest/)).

In the examples that follow, we'll be using HTTP syntax.

### Discovery document

A discovery document is used to retrieve metadata about the Customer's Canvas identity provider. This endpoint contains information about all other API endpoints, so it's the only one you need to hardcode (or add to your app's configuration).

The address of this endpoint is `https://<base-url>/.well-known/openid-configuration`. If you open the [discovery document address](https://customerscanvashub.com/.well-known/openid-configuration) in your browser, you'll see a JSON document like this:

```json
GET https://<base-url>/.well-known/openid-configuration
{
  "issuer": "https://customerscanvashub.com",
  "jwks_uri": "https://customerscanvashub.com/.well-known/openid-configuration/jwks",
  "authorization_endpoint": "https://customerscanvashub.com/connect/authorize",
  "token_endpoint": "https://customerscanvashub.com/connect/token",
  "userinfo_endpoint": "https://customerscanvashub.com/connect/userinfo",
  "end_session_endpoint": "https://customerscanvashub.com/connect/endsession",
  ... /* Omitted for brevity */
}
```

This document is generally stable and unlikely to change frequently. So, you may be tempted to just hardcode the addresses of the endpoints you need in your code. However, unless you are building a one-off app or experiment with API, we recommend fetching and caching these addresses on app launch rather than hardcoding them in your code.

### Authorize

This endpoint is utilized to display the login screen, which is an integral part of Implicit and Authorize Code flows. You can obtain the address for this endpoint by using the `authorization_endpoint` parameter in a discovery document.

:::note
If you are seeking information about how to obtain a token for the Client Credentials flow, please skip ahead to the next section.
:::

Like the Document Discovery endpoint, it is also a GET request. It requires passing a number of arguments as query parameters. Different combinations of these parameters are suitable for various scenarios. For a comprehensive list of these parameters, please refer to the [Authorize endpoint reference](https://identityserver4.readthedocs.io/en/latest/endpoints/authorize.html). For the purpose of this article, we will focus solely on our specific scenarios.

#### Authorizing for Implicit flow

To start the authentication with the Implicit flow, make the following request:

```bash
GET https://<base-url>/connect/authorize?
    client_id=9f4deec9-xxxx-xxxx-xxxx-e8faae92ab1c
  & scope=Assets_full Projects_full
  & redirect_uri=https://example.com/myapp/login-callback
  & state=123456789
  & response_type=token
```

:::note
Line breaks and white spaces are added for better readability.
:::

When making the request, use the following parameters:

- `client_id`: copy the client ID from your External App settings.
- `scope`: insert a space-separated list of required permissions (see the `scopes_supported` in the Discovery Document).
- `redirect_uri`: specify a URL where the user is redirected after successful login. If it is not specified in the External App settings, it will be rejected.
- `state`: pass a value that will be echoed back to the `redirect_uri`. This is explained in more detail below.
- `response_type`: for the Implicit flow you should use `token`.
 
Once you call this endpoint, the user will be redirected to the Customer's Canvas login page. After the user successfully authorizes the request, they will be redirected to the URL specified in the `redirect_uri` parameter. This URL will include a fragment that looks like this:  

```bash
https://<YOUR REDIRECT URL>#access_token=<ACCESS TOKEN>&token_type=Bearer&expires_in=3600&scope=<SCOPES>&state=<YOUR STATE>
```

You will need to parse this fragment string and use the `access_token` and `state` values.

It's likely that you'll need to use the access token not only immediately after receiving it but also in future interactions. As a result, you'll need to establish a "login session" and preserve the state of this session, perhaps by storing it in a database. Before invoking the Authorize endpoint, you can create an empty login session record and utilize its ID as a state parameter when calling the Authorize endpoint. 

When the `redirect_url` is invoked, Customer's Canvas will pass this ID back via the `state` in the URL fragment. This will enable you to identify your session and complete the login process. For instance, you could save the access token to the login session state at this point.

Another function of the `state` parameter is to ensure that no one attempts to access a callback URL directly.

Once you have an access token, you can use it in the API calls. Read on for further details.

#### Authorize for Authorization Code flow (no PKCE)

When you set up the Authorization Code flow and disable the PKCE option, the usage of the Authorize endpoint is strikingly similar to the Implicit flow. The only difference is that you must specify the `response_type` as `code`: 

```bash
GET https://<base-url>/connect/authorize?
    client_id=9f4deec9-xxxx-xxxx-xxxx-e8faae92ab1c
  & scope=Assets_read Private_assets_update
  & redirect_uri=https://example.com/myapp/login-callback
  & state=123456789
  & response_type=code
```

:::note
Line breaks and white spaces have been inserted between & and parameters for improved readability.
:::

If the user is signed in, you will be redirected to your `redirect_uri`, which will contain additional query string parameters: 

```bash
https://example.com/myapp/login-callback?code=<AUTH CODE>&scope=<SCOPES>&state=<YOUR STATE>
```

The `code` will consist of a one-time-use key that you must utilize with the Token endpoint (see below) to obtain an access token.

#### Authorize for Authorization Code flow (with PKCE)

The Authorization Code flow without PKCE is susceptible to a security vulnerability. If attackers intercept the authorization code and activate it before you, they can obtain an access token on your behalf. However, PKCE can prevent this by generating a special secret value, known as a _code verifier_, and creating a corresponding _code challenge_ based on it.

To create a code verifier, you need to generate a random string with a length between 43 and 128 characters. It's crucial to note that shorter values could lead to error messages that are difficult to troubleshoot, so ensure that the string is long enough. While it's possible to use a constant value, generating a new code verifier for each request and storing it in a login session enhances security.

A code challenge is a base64-encoded SHA-256 hash value of the code verifier string. Here's a pseudo-code example:

```js
var code_verifier = GenerateRandom43CharacterString();
var code_challenge = EncodeBase64(CreateHash("SHA256", code_verifier));
```

:::tip
Most web stacks have implemented the SHA-256 hash calculation. For example, in C#, you can use the [System.Security.Cryptography.SHA256 class](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.sha256), while PHP offers the [hash function](https://www.php.net/manual/en/function.hash.php) with $algo = sha256, and NodeJS provides the [crypto module](https://nodejs.org/api/crypto.html).
:::

Once you obtain the code challenge value, you can call the Authorize endpoint like this: 

```bash
GET https://<base-url>/connect/authorize?
    client_id=9f4deec9-xxxx-xxxx-xxxx-e8faae92ab1c
  & scope=Assets_read Private_assets_update
  & redirect_uri=https://example.com/myapp/login-callback
  & state=123456789
  & code_challenge=UiQJkoYcXeFjsgrdgTfUXIwJRAV07SX4MDrq8AoZhP0
  & code_challenge_method=S256
  & response_type=code
```

Note that in addition to `code_challenge`, there is an additional parameter, `code_challenge_method`, which should always be equal to `S256`. At this time, no other values are supported.

The remaining flow is nearly identical to the scenario without PKCE, with the only exception being that you need to send the code verifier when using the Token endpoint, as explained further. 

### Requesting an Access Token

To request an access token from the Customer's Canvas identity provider, you can utilize the Token endpoint. The address of the endpoint can be obtained through the `token_endpoint` parameter of the Discovery Document.

:::important
Please note that for the Implicit flow, the Authorize endpoint already returns an access token. Hence, there is no need to request it separately. If you are implementing the Implicit flow, you can skip ahead to the next section.
:::

It is important to keep in mind that the Token endpoint call should be a POST request with parameters passed with the `application/x-www-form-urlencoded` content type. The parameters that need to be included depend on the authentication type you choose.

#### Requesting an Access Token for the Client Credentials Flow

To acquire a token for the Client Credentials flow, you need to send the following x-www-form-urlencoded POST request:

```bash
POST https://<base-url>/connect/token
  Content-Type: application/x-www-form-urlencoded

  client_id=9f4deec9-xxxx-xxxx-xxxx-e8faae92ab1c
  client_secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  scope=Assets_full Projects_full
  grant_type=client_credentials
```

:::note
Line breaks have been added, and form encoding has been removed for better readability.
:::

The response from this request will be in the form of a JSON object that includes the access token, its expiration time, token type, and scope. 

```json
{
    "access_token": "<YOUR TOKEN HERE>",
    "expires_in": 3600,
    "token_type": "Bearer",
    "scope": "Assets_full Projects_full"
}
```

The token should be used within the value specified in the expires_in parameter (in seconds). After the token expires, you can request another one.

#### Requesting an Access Token for the Authorization Code Flow

The process of obtaining a token for the Authorization Code flow is similar to that of the Client Credentials flow, with a few additional steps: 

1. Use the `grant_type` parameter set to `authorization_code`. 
2. Include the `code` parameter, which contains the code received in the redirect URL you passed to the Authorize endpoint.
3. Include the `redirect_uri`, which is the same as the one for the Authorize endpoint.
4. If you use PKCE, you must include the string used to build a `code_challenge` as a `code_verifier`. It is essential to note that you need to send the original string, not its hash representation, unlike the Authorize endpoint. 

You can send the following x-www-form-urlencoded POST request to acquire the access token:

```bash
POST https://<base-url>/connect/token
  Content-Type: application/x-www-form-urlencoded

  client_id=9f4deec9-xxxx-xxxx-xxxx-e8faae92ab1c
  client_secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  scope=Assets_full Projects_full
  code=1234567xyz
  code_verifier=pNmzR9QCVJzqoFbHu2rEWuWQR130SFAnSPdZPnOtFso
  redirect_uri=https://example.com/myapp/login-callback
  grant_type=authorization_code
```

:::note
As before, line breaks have been added, and form encoding has been removed for better readability.
:::

The response to this request will also be a JSON object containing the access token, its expiration time, token type, and scope. 

```json
{
    "access_token": "<YOUR TOKEN HERE>",
    "expires_in": 3600,
    "token_type": "Bearer",
    "scope": "Assets_full Projects_full"
}
```

#### Updating a Token Without Re-Login

When a token expires, you must request a new one. For the Client Credentials flow, this is acceptable, but for the Authorization Code flows, users may find it inconvenient to re-login every hour (or another period you configure). Fortunately, the Customer's Canvas identity service supports _refresh tokens_, which can be used to receive new access tokens with the updated expiration date.
 
:::important
Refresh tokens are not supported for the Implicit flow due to security reasons.
:::

To obtain a refresh token, you should slightly modify the standard flow of receiving an access token. It is necessary to request an extra scope - `offline_access`. Your Authorize endpoint call should look like this: 

```bash
GET https://<base-url>/connect/authorize?
    client_id=9f4deec9-xxxx-xxxx-xxxx-e8faae92ab1c
  & scope=offline_access Assets_read Private_assets_update
  & redirect_uri=https://example.com/myapp/login-callback
  ... /* other params omitted for brevity */
```

After receiving a code and requesting a token, the response will include the `refresh_token` in addition to the `access_token`:

```json
{
    "access_token": "<YOUR ACCESS TOKEN>",
    "expires_in": 3600,
    "token_type": "Bearer",
    "refresh_token": "<YOUR REFRESH TOKEN>",
    "scope": "Assets_full Artifacts_full offline_access"
}
```

Save this refresh token along with the access token in the login session, and remember to save the expiration time. Every time you use the access token, check if the token is about to expire (e.g., less than 60 seconds left). If so, use the Token endpoint with the `grant_type` set to `refresh_token`. Pass your current refresh token like this:

```bash
POST https://<base-url>/connect/token
  Content-Type: application/x-www-form-urlencoded

  client_id=9f4deec9-xxxx-xxxx-xxxx-e8faae92ab1c
  client_secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  refresh_token=<YOUR CURRENT REFRESH TOKEN>
  grant_type=refresh_token
```

This will return a new pair of access and refresh tokens. The new expiration date will be incremented by the normal expiration period configured in the External App settings. Update these values in the login session and continue using the updated access token as usual.

### End session 

Finally, let's discuss the proper way to sign out your users. 

:::important
This applies to the Implicit and Authorize Code flows only. 
:::

To accomplish this, you will need the _identity token_ (or the *id_token*) that contains user information. Similar to the refresh token, you can obtain the identity token as part of the regular authentication flow.

The Authorize endpoint call will look slightly different depending on whether you use Implicit or Authorize Code call.

#### Obtain id_token for the Implicit flow

To obtain the id_token for the Implicit flow, you need to do three things: 

1. Pass an additional scope - `openid`.  
2. Add `id_token` to the `response_type`, making it `id_token token`.
3. Add a new parameter - `nonce`, which should be a random string unique to each request.

Here's an example endpoint call:

```bash
GET https://<base-url>/connect/authorize?
    client_id=9f4deec9-xxxx-xxxx-xxxx-e8faae92ab1c
  & scope=openid Assets_read Private_assets_update
  & redirect_uri=https://example.com/myapp/login-callback
  & response_type=id_token token
  & state=123456789
  & nonce=<SOME UNIQUE RANDOM STRING>
```

As a result, the fragment of the redirect URL will include an additional element - `id_token`:

```bash
https://example.com/myapp/login-callback#id_token=<YOUR ID TOKEN>&access_token=<YOUR ACCESS TOKEN>&token_type=Bearer&expires_in=3600&scope=openid%20Assets_full%20Artifacts_full&state=1234&session_state=<...>
```

This token can be parsed as a regular JWT token. But what is more important, you can use it in the EndSession endpoint, as explained below. 

#### Obtain id_token for the Authorize Code flow

To obtain the id_token for the Authorize Code flow, add `openid` to the scope. No need to change the `response_type` or pass the `nonce`. Here's an example endpoint call:

```bash
GET https://<base-url>/connect/authorize?
    client_id=9f4deec9-xxxx-xxxx-xxxx-e8faae92ab1c
  & scope=openid offline_access Assets_read Private_assets_update
  & redirect_uri=https://example.com/myapp/login-callback
  ... /* omitted for brevity */
  & response_type=code
```

:::note
As you can see, we have combined `openid` with `offline_access` to be able to get not only the id_token but also the refresh token.
:::

After you get the authorization code and pass it to the Token endpoint, the resulting JSON document will include all tokens: 

```json
{
    "id_token": "<YOUR ID TOKEN>",
    "access_token": "<YOUR ACCESS TOKEN>",
    "expires_in": 3600,
    "token_type": "Bearer",
    "refresh_token": "<YOUR REFRESH TOKEN>",
    "scope": "openid Assets_full Artifacts_full offline_access"
}
```

#### Using the EndSession endpoint

To use the EndSession endpoint, obtain the endpoint address from the `end_session_endpoint` property of the Discovery Document. Send a GET request to this address to sign out the user. This endpoint requires passing only three parameters:

```bash
GET https://<base-url>/connect/endsession?
    id_token_hint=<YOUR ID TOKEN>
  & post_logout_redirect_uri=https://example.com/myapp/logout-callback
  & state=123456789
```

Here's what you need to know about these parameters:

- `id_token_hint`: This is an id_token that you obtained earlier. It identifies the user that you want to sign out.
- `post_logout_redirect_uri`: This is the URL of an endpoint in your app that will finalize the logout process by removing the login session, etc. It must be one of the URLs that you added to the External App settings as **Post logout redirect URIs**.
- `state`: This is the state ID that will be passed to the post-logout URL through the query string.

Once you have implemented the post-logout endpoint, it's a good idea to redirect the user to the home or login page.

## Making API Calls

Once you have successfully obtained an access token, you can proceed with making calls to the Customer's Canvas API by utilizing the Bearer Token. This can be accomplished by adding an `Authorization` header to your request, which should look like the following:

```bash
GET https://api.customerscanvashub.com/api/...
  Authorization: Bearer <YOUR ACCESS TOKEN HERE>
```

As long as you communicate with the API within the permissible scopes, and the token is not expired, Customer's Canvas will readily accept your tokens.
