---
title: "Use OAuth2 to Access REST API"
canonical: "https://help.agiloft.com/space/HELP/43716464/Use%20OAuth2%20to%20Access%20REST%20API"
format: markdown
---
For secure and standardized access control, the REST API supports the [OAuth 2.0](https://www.rfc-editor.org/rfc/rfc6749) framework for authorization. OAuth 2.0 allows applications to obtain scoped access to protected resources without exposing user credentials. To accommodate different use cases, the REST API supports multiple grant types. For user-centric applications, Authorization Code flow is supported, including the enhanced Authorization Code with Proof Key for Code Exchange ([PKCE](https://datatracker.ietf.org/doc/html/rfc7636)), which is recommended for public clients. For machine-to-machine (M2M) communication without user interaction, the API supports Client Credentials flow.

Agiloft provides two authorization mechanisms for REST API access:

- **OAuth 2.0** is the recommended protocol for new integrations and third-party applications.
- **[ExtAuth](https://agiloft-public.atlassian.net/wiki/spaces/HELP/pages/703889445)** is Agiloft’s legacy authorization mechanism that remains available for backward compatibility with existing integrations and internal use cases.

Both mechanisms issue bearer access tokens for the REST API, but they use different endpoints, configuration, and authorization models.

# OAuth 2.0

To set up OAuth 2.0 access, you create an API application in your KB to register the client that will access the REST API. The registration defines the token grant type, user account to use for data access permissions, and client identifier. Once your client is registered, you authorize it by making a series of API calls to get an access token. Once the token is issued, it’s used to authenticate subsequent API requests.

This article guides you through the steps to create an API application and get access to the API.

> ℹ️ **Prerequisites**
> ℹ️ 
> ℹ️ - API services are available with the new Platform edition of Agiloft, but on older editions, they require either an Advanced or Premium edition of Agiloft.
> ℹ️ - When you register an OAuth 2.0 client for REST API access, you link each client to a specific Agiloft user account. This account functions as a service user. Access tokens issued to the client represent this account, and all REST API calls made through the client run with the identity and permissions of the account, regardless of who initiates the request from the external application. When creating API service user accounts, keep the following notes in mind:
> ℹ️   - The accounts must be native Agiloft accounts. LDAP accounts aren’t compatible.
> ℹ️   - Create a different account for each OAuth client. If you associate multiple clients with the same account, acquiring or refreshing the access token for one client invalidates the tokens for all other clients.
> ℹ️   - Each account requires an Admin or Standard license.
> ℹ️   - Give the accounts access to the records you plan to interact with via the API by adding the appropriate [groups](https://agiloft-public.atlassian.net/wiki/spaces/HELP/pages/43714429) to the user records.
> ℹ️   - When your application sends an authorization API request, use the credentials of the account in the OAuth client configuration to authenticate and authorize the request.

# > Macro (anchor)

Creating an API Application

The OAuth 2.0 setup begins with registering your client as a new API application. To create an API application:

1. Go to **Setup > Integration > OAuth2 Client Setup**.
2. Click Deploy, Upgrade, or Configure, depending on what you see:
  - **Deploy**: The OAuth2 client hasn't been deployed yet. Clicking Deploy configures the OAuth2 client for use in your KB, which can take a few minutes to complete.
  - **Upgrade**: If Upgrade appears, the OAuth2 client is deployed but there’s an upgrade available, such as to add support for the PKCE grant type. Clicking Upgrade upgrades the client.
  - **Configure**: The OAuth2 client has already been deployed. Clicking Configure takes you to the API Application screen.
3. On the API Application screen, click New to open the OAuth2 Application Settings wizard.
4. Complete the required fields:
  1. **Authorization Grant Type**: The type of authorization flow to use for your application.
  2. **Name**: The name the application will use with the REST API.
  3. **Display Name**: The name of the application that appears in your KB.
  4. **Associate this Application with Contact ID**: This field is automatically populated when you select a user in the Full Name field. It’s the ID of the user associated with the application.
  5. **Full Name**: The name of the service user account to associate with this application. All REST API calls made through the client run with the identity and permissions of this account.
  6. **Redirect URI**: For authorization code flows, this is the endpoint where the authorization server should send the user (and authorization code) after they log in and grant consent. You can specify multiple redirect URIs in a comma-separated list.
  7. **Token Expiry in Minutes**: The amount of time in minutes before the access token expires. The default value is 15, and the valid range is from 1 to 60.
5. Click Apply Changes.
6. Now click Enable. This activates the application and generates the Client ID and Client Secret, which are used during the token exchange.

> 📝 If you need to block your application for any reason in the future, you can click Disable, which replaces Enable after it's clicked.

Now that your application is registered as an API client, complete the process to [get API acess](#request_token).

## Changing Application Settings

Verify that your application settings are correct so you don't need to change them later. If you need to change your application's settings but have already completed the authentication procedure described below, you need to re-authenticate for your changes to take effect. If you need to make changes but have already received an access token, you need to revoke the access token, make the changes, and then obtain a new access token for your changes to take effect. See [Revoking Tokens](https://agiloft-public.atlassian.net/wiki/spaces/hdrafts/pages/44027993) for more information.

Changes to the values in the Associate this Application with Contact ID field or the Redirect URI field can sometimes block your application. If this happens, recreate the application configuration with the correct settings.

> 📝 You can change the Token Expiry in Minutes value without performing the re-authentication procedure. Changes to this field take effect when the next access token is requested.

# > Macro (anchor)

Getting API Access

After the [API application](#api_application) is created, authorize your client by sending API requests to the server’s authorization and/or token endpoints. The type of requests you make depend on the token grant type specified in the API application registration. Select your grant type to view the requests:

- [Authorization Code Grant](#authorization_code)
- [Client Credentials Grant](#client_credentials)

## > Macro (anchor)

Authorization Code Grant

This section describes the API requests to send to obtain an access token. First, you send a request for an authorization code, then you exchange the code for an access token.

> ℹ️ **Prerequisites for PKCE**
> ℹ️ 
> ℹ️ For implementations with PKCE, your application must generate a code verifier and then derive a code challenge from that value before sending an authorization request. The app sends the code challenge in the authorization request, while keeping the original code verifier secret until the token request. When the authorization server receives the token request with the code verifier, it validates that the code verifier correctly produces the code challenge, ensuring both requests originate from the same application. The list below describes the requirements for the code verifier and code challenge values.
> ℹ️ 
> ℹ️ - code_verifier is a random, high-entropy string that includes a minimum of 43 and maximum of 128 of the following characters: [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
> ℹ️ - code_challenge is derived from the code verifier using one of these methods:
> ℹ️   - Plain: With the plain method, code_challenge is identical to the code_verifier.
> ℹ️   - S256: This is the recommended method. For S256, code_challenge is the Base64URL-encoded SHA-256 hash of the code_verifier: `BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))`
> ℹ️ 
> ℹ️ For more information, see [Protocol](https://datatracker.ietf.org/doc/html/rfc7636#section-4) in the RFC 7636 specification.

### Authorization Request

The authorization request initializes the OAuth process. To make the request, the client should redirect you to make a POST request to the authorization endpoint,  `/ewws/oauth`. When you send the request, you’re asked to authenticate and authorize the request. When you log in, supply the credentials of the service user from the OAuth client configuration.

Authorization requests have the following requirements:

- Content-Type must be `application/x-www-form-urlencoded`.
- Values with special characters must be URL-encoded.
- Include the following query string parameters:

| **Parameter** | **Value** | **Required** | **Description** |
| --- | --- | --- | --- |
| response_type | code | Yes | Defines the response type and must always have a value of `code`. |
| client_id | From the API application configuration | Yes | The client identifier from the API application configuration. |
| redirect_uri | Absolute URI from the API application configuration | Yes | This value must match one of the values in the Redirect URI field in the API application configuration |
| scope | permissions_for:CONTACT_ID | Yes | Defines the permissions that the user is asked to approve, which are determined by the Contact ID defined in the API application configuration. For example, if the Associate this Application with Contact ID field is 222, this parameter is set to `permissions_for:222`. |
| state | Any string | Recommended | Specifies a value to return to the client as a parameter at the end of the authorization process, which verifies the validity of the request. Although this parameter is not required, we highly recommend using it to protect against cross-site request forgery (CSRF), as described in [RFC 6749](https://tools.ietf.org/html/rfc6749#section-10.12). |
| code_challenge | `code_verifier` in plain text  
or  
`BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))`(recommended) | Required for Authorization Code with PKCE | Lists either the plain text version of the code_verifier string or the Base64URL-encoded SHA-256 hash of the code_verifier string. |
| code_challenge_method | `plain` or `S256` (recommended) | Required if code_challenge is SHA-256 encoded | Defaults to `plain` if the parameter is omitted from the request. Include `code_challenge_method=S256` if code_challenge is SHA-256 encoded. |

For readability, values in the following example requests aren’t URL-encoded.

**Example HTTP Request without PKCE**

```
POST /ewws/oauth HTTP/1.1
Host: example.agiloft.com
Content-Type: application/x-www-form-urlencoded

response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=https://my.app.com/callback&scope=permissions_for:213&state=LQFN...
```

**Example HTTP Request with PKCE**

```
POST /ewws/oauth HTTP/1.1
Host: example.agiloft.com
Content-Type: application/x-www-form-urlencoded

response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=https://my.app.com/callback&scope=permissions_for:213
&state=LQFN...&code_challenge=W75H5H4DE...&code_challenge_method=S256
```

**Successful Authorization Request**

If the request succeeds, the following query string parameters are included in the response:

| **Parameter** | **Value** |
| --- | --- |
| state | The value of the state parameter from the authorization request. |
| code | The authorization code for use in the upcoming access token request. This code is valid for five minutes. <span style="color: #333333">Protecting the authorization code, which is a secret, is one of the security implications of this OAuth flow.</span> |
| client | Provides system information. |

**Example Response to a Successful Request**

```
HTTP/1.1 302 Found
Location: https://my.app.com/callback?client=&state=LQKFNL023478_3259423&
    code=teSxRze6M4sTl%2B3...
```

**Failed Authorization Request**

If the request fails, the following query string parameters are sent in the response:

| **Parameter** | **Value** |
| --- | --- |
| error | Defines the error code. See below for a description of each error code. |
| error_description | Describes why the request failed. |

The following error codes are possible:

| **Code** | **Description** |
| --- | --- |
| invalid_request | The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. |
| unauthorized_client | The client is not authorized to request an authorization code using this method. |
| access_denied | The resource owner or authorization server denied the request. |
| unsupported_response_type | The authorization server does not support obtaining an authorization code using this method. |
| invalid_scope | The requested scope is invalid, unknown, or malformed. See the scope parameter description in the Authorization Request section above. |
| server_error | The authorization server encountered an unexpected condition that prevented it from fulfilling the request. |

### Access Token Request

After the authorization request, send a POST request to the token endpoint,  `/ewws/otoken`, to exchange the authorization code for an access token.

Token requests have the following requirements:

- Content-Type must be `application/x-www-form-urlencoded`.
- Values with special characters must be URL-encoded.
- Include the following query string parameters:

| **Parameter** | **Value** | **Required** | **Description** |
| --- | --- | --- | --- |
| grant_type | authorization_code or authorization_code_pkce | Yes | Defines the grant type, which is `authorization_code` or `authorization_code_pkce` if you are using PKCE. |
| code | The authorization code obtained in the authorization response | Yes | Confirms that the previous step was successful. |
| client_id | Obtained from the OAuth2 Application Settings wizard | Yes | Identifies the application. |
| redirect_uri | Must match the value used in the authorization request | Yes | This value must belong to the set of values specified in the OAuth2 Application Settings wizard. |
| code_verifier | For PKCE, the original code verifier string that code_challenge is derived from | Required for PKCE | The authorization server compares this value to the code_challenge to verify that the client requesting the token is the same client that sent the authorization request. |

For readability, values in the following example requests aren’t URL-encoded.

**Example HTTP Request without PKCE**

```
POST /ewws/otoken HTTP/1.1
Host: example.agiloft.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=EFLJH...&client_id=Bvn7k4fI...&redirect_uri=https://my.app.com/callback
```

**Example HTTP Request with PKCE**

```
POST /ewws/otoken HTTP/1.1
Host: example.agiloft.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=EFLJH...&client_id=Bvn7k4fI...&redirect_uri=https://my.app.com/callback&code_verifier=0MSPgIukJ7...
```

**Successful Access Token Response**

The authorization code from the request is exchanged for OAuth2 tokens, and the server returns a JSON array with the following keys:

| **Parameter** | **Value** |
| --- | --- |
| access_token | The access token, which can be used in the authorization header in the Agiloft REST API. |
| refresh_token | The refresh token, which can be used to get a new access token. Refresh tokens expire after 28 days of inactivity. |
| token_type | The value will always be `Bearer`. |
| expires_in | The expiration time in minutes for the access token. |

**Example Token Response**

```
{
  "access_token":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIyX2FkbWluI...",
  "refresh_token":"LKHEFOP932875KJGKJG32423542LHLKHFD...",
  "token_type":"Bearer",
  "expires_in":900
}
```

### Refresh Request

At any time, the client can use the refresh token to receive a new access token. To request a refresh token, send a POST to the `/ewws/otoken` endpoint. Refresh requests have the following requirements:

- Content-Type must be `application/x-www-form-urlencoded`.
- Values with special characters must be URL-encoded.
- Include the following query string parameters:

| **Parameter** | **Value** | **Required** | **Description** |
| --- | --- | --- | --- |
| grant_type | refresh_token | Yes | The value must always be `refresh_token`. |
| md5_secret | The first 20 characters of the Client Secret from the API Application settings | Yes | Authenticates the application. |
| refresh_token | Refresh token received during the previous step | Yes | Defines the refresh token. |

**Example HTTP Refresh Request**

```
POST /ewws/otoken HTTP/1.1
Host: example.agiloft.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&md5_secret=F64EC9CE9852EE154696&refresh_token=LKHEFOP932875KJGKJG32423542LHLKHFD_FDKLJ.OJ%3D%3D
```

The server returns a JSON array with the following keys:

| **Parameter** | **Value** |
| --- | --- |
| access_token | The access token, which can be used as an authorization header in the Agiloft REST API. |
| token_type | The value will always be `Bearer`. |
| expires_in | The expiration time in seconds of the access token. |

**Example Refresh Response**

```
{
  "access_token":"wehRT74iOiJIUz...",
  "token_type":"Bearer",
  "expires_in":900
}
```

## > Macro (anchor)

Client Credentials Grant

To acquire an access token using client credentials flow, send a POST request to the token endpoint, `/ewws/otoken`. Token requests have the following requirements:

- Content-Type must be `application/x-www-form-urlencoded`.
- Values with special characters must be URL-encoded.
- Include the following form parameters in the request body:

| **Form Parameter** | **Value** | **Required** | **Description** |
| --- | --- | --- | --- |
| grant_type | client_credentials | Yes | Defines the token grant type. |
| client_id | Client ID from the API application settings | Yes | Unique identifier for the application. |
| client_secret | Client Secret from the API application settings | Yes | The confidential credential issued to the API application. |

**Example HTTP Request**

```
POST /ewws/otoken HTTP/1.1
Host: example.agiloft.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET
```

**Example cURL Request**

```
curl -X POST "https://example.agiloft.com/ewws/otoken"
  -H "Content-Type: application/x-www-form-urlencoded"
  --data-urlencode "grant_type=client_credentials"
  --data-urlencode "client_id=YOUR_CLIENT_ID"
  --data-urlencode "client_secret=YOUR_CLIENT_SECRET"
```

**Example Response**

The response includes the token, token type, and token expiration value in seconds.

```
{
  "access_token": "eyJhbGciOiJSUzUxMiJ9.ey...",
  "token_type": "Bearer",
  "expires_in": 3600
}
```

You don’t send refresh requests with client credentials flow. When the access token expires, resend the above token request to obtain a new token.

# Revoking Tokens

Access tokens and refresh tokens can be revoked at any time by the authorizing user. REST operations cannot be performed with a token that has been revoked. If an access token is revoked and it has a corresponding refresh token, the refresh token is also revoked. If a refresh token is revoked, all the access tokens issued from that refresh token are also revoked. 

Revoke tokens by making a POST request to the revoke endpoint, `/ewws/orevoke`.  Revoke requests have the following requirements:

- Content-Type must be `application/x-www-form-urlencoded`.
- Values with special characters must be URL-encoded.
- Include the following query string parameter:

| **Parameter** | **Value** | **Required** | **Description** |
| --- | --- | --- | --- |
| revoke_for | OAuth2 refresh token or Client Secret key from API Application Settings wizard | Yes | Defines the refresh token or Client Secret Key. |

**Example HTTP Request**

```
POST /ewws/orevoke HTTP/1.1
Host: example.agiloft.com
Content-Type: application/x-www-form-urlencoded

revoke_for=LKHEFOP932875KJGKJG32423542LHLKHFD_FDKLJ.OJ%3D%3D
```

## Response to Revoking a Token

If the request to revoke the token succeeds, an HTTP success code 200 is returned with an empty body or without any body at all. If the request fails, an HTTP code 400 is returned with the error code `INVALID_REQUEST`.

**Example Response to a Failed Request**

```
{
  "error" : "INVALID_REQUEST",
  "error_description" : "Invalid token."
}
```

#### Related articles

> Macro (contentbylabel)