# Exchange client ID and secret for an access token

To integrate JetBrains Central Console features and services with your own applications through a service account, the service account's client ID and client secret need to be exchanged for an access token. The exchange process takes place through the standard OAuth 2.0 Client Credentials flow, which is intended for machine-to-machine (M2M) applications.

For more information about OAuth and the client credentials flow, see the following resources:

* [Client Credentials Flow Overview](https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow) (auth0.com)

* [Specification of the Client Credentials Flow (OAuth 2.0 RFC 6749, section 4.4)](https://tools.ietf.org/html/rfc6749#section-4.4) (ietf.org)

## Prerequisites

For a client to exchange JetBrains Central Console client ID and client secret for a token, it must meet the following requirements:

* The client knows its own client ID and client secret and can request access to resources only using its own credentials.

* The [Client Credentials](https://tools.ietf.org/html/rfc6749#section-4.4) grant type must only be used by confidential clients (clients that can store the credentials securely).

## Access token request

The client makes a POST request to the following token endpoint:

```PLAINTEXT
https://oauth.account.jetbrains.com/api/rest/oauth2/token
```

The request must contain the following headers:

* `Authorization`: Uses HTTP Basic Authentication and passes base64-encoded client ID and client secret in the following format: ```HTTP_REQUEST Authorization: Basic base64(client_id + ":" + client_secret) ``` The encoding should be UTF-8 before converting to Base64. > **Warning:** > Never include your `client_secret` in client-side code. This flow must only be executed from a secure backend server.

* `Content-Type`: Must be set to `application/x-www-form-urlencoded`.

The request body must include the following parameters:

* `grant_type`: always set to `client_credentials` for the Client Credentials flow.

* `scope` parameter: must be set to `jcp-public`.

For a detailed specification and examples of access token requests, see [Request and response specification](#request-response-specification).

## Request and response specification

Host: `oauth.account.jetbrains.com`

OpenAPI endpoint: POST /api/rest/oauth2/token

The client makes a request to the token endpoint using its client credentials (client ID and client secret) to obtain an access token.

### Request parameters

**Request**

Security

- **HTTP** (Basic): Client authentication via HTTP Basic Auth. The credentials should be formatted as client_id:client_secret and then Base64-encoded.

Header

- **Authorization** (string, required): Client authentication via HTTP Basic Auth. The credentials should be formatted as client_id:client_secret and then Base64-encoded.

Body

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

- **application/x-www-form-urlencoded** (object, required)
- **grant_type** (string, required): Must be set to client_credentials.
- **scope** (string): Must be jcp-public.

**HTTP**

```HTTP_REQUEST
POST /api/rest/oauth2/token
Host: oauth.account.jetbrains.com
Authorization: Basic <BASE64(CLIENT_ID:CLIENT_SECRET)>
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&scope=jcp-public
```

**cURL**

```BASH
curl -X POST https://oauth.account.jetbrains.com/api/rest/oauth2/token \
-u "<CLIENT_ID:CLIENT_SECRET>" \
-d "grant_type=client_credentials" \
-d "scope=jcp-public"
```

### Responses

**Response 200**

Content type: application/json

If the access token request is valid and authorized, the authorization server issues an access token. This flow provides an access token only. Refresh tokens are not supported.

- **application/json** (object)
- **access_token** (string, required): The access token issued by the authorization server.
- **token_type** (string, required): The type of issued token. The returned value is Bearer.
- **expires_in** (integer): The duration (in seconds) for which the access token is valid. The value of 3600 indicates the token expires in one hour. Clients should cache the token and only request a new token when the current one is nearing expiration.
- **scope** (string): Must be jcp-public.
- **Cache-Control (Header)** (string, required): Cache control header. The server always returns this header with the value no-store.

**200**

```JSON
{
    "access_token": "<TOKEN>",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "jcp-public"
}
```

**Response 400**

Content type: application/json

Request is not valid.

- **application/json** (OAuthError)
- **error** (Enum, required): Error identifier. Available values:

invalid_request

invalid_client

invalid_grant

unauthorized_client

unsupported_grant_type

invalid_scope
For more information, see Error responses.
- **invalid_request**
- **invalid_client**
- **invalid_grant**
- **unauthorized_client**
- **unsupported_grant_type**
- **invalid_scope**
- **error_code** (integer): The HTTP response code for the error.
- **error_description** (string): Human-readable explanation of the error.
- **error_uri** (string uri): URI with more information about the error.

**400**

```JSON
{
    "error": "unsupported_grant_type",
    "error_code": 400,
    "error_description": "The authorization grant type is not supported by the authorization server",
    "error_uri": "https://jb.gg/console/oauth/unsupported-grant-type"
}
```

**Response 401**

Content type: application/json

Client authentication failed.

- **application/json** (OAuthError)
- **error** (Enum, required): Error identifier. Available values:

invalid_request

invalid_client

invalid_grant

unauthorized_client

unsupported_grant_type

invalid_scope
For more information, see Error responses.
- **invalid_request**
- **invalid_client**
- **invalid_grant**
- **unauthorized_client**
- **unsupported_grant_type**
- **invalid_scope**
- **error_code** (integer): The HTTP response code for the error.
- **error_description** (string): Human-readable explanation of the error.
- **error_uri** (string uri): URI with more information about the error.

**401**

```JSON
{
    "error": "invalid_client",
    "error_code": 401,
    "error_description": "Service with id \"test-123\" was not found",
    "error_uri": "https://jb.gg/console/oauth/invalid-client"
}
```

## Error responses

The following table includes a list of error responses and their corresponding descriptions in accordance with [Section 5.2](https://tools.ietf.org/html/rfc6749#section-5.2) that defines error responses in the RFC 6749 standard.

| Error identifier | Description | Solution |
| --- | --- | --- |
| `invalid_request` |     The request is missing a required parameter, includes an unsupported parameter value (other than `grant_type`), repeats a parameter, includes multiple credentials, uses more than one mechanism for authenticating the client, or is otherwise malformed.     |      * Ensure request body includes the `grant_type` parameter.    * Set the correct header: `Content-Type: application/x-www-form-urlencoded`.    * Remove duplicate or unexpected parameters.    |
| `invalid_client` |     Client authentication failed for reasons such as unknown client, no client authentication included, or unsupported authentication method.     |      * Verify that client ID and client secret are correct.    * Ensure the header format is correct: `Authorization: Basic base64(client_id:client_secret)`    |
| `invalid_grant` |     The provided authorization grant is not valid, has expired, has been revoked, does not match the redirection URI used in the authorization request, or was issued to another client.     |      * Request a new access token. If the error persists, verify that the service account has not been deleted or revoked.    |
| `unauthorized_client` |  The client is not authorized to use this authorization grant type.  |      * Ensure that the client is a registered service in JetBrains Central Console.    |
| `unsupported_grant_type` |  The authorization server does not support the specified authorization grant type.  |      * Make sure to use `client_credentials` as the value for `grant_type`.    |
| `invalid_scope` |  The requested scope is not valid, is unknown, malformed, or exceeds the scope granted by the resource owner.  |      * Ensure the requested scope is `jcp-public`.    |

