# OAuth

Request an OAuth 2.0 token using Basic Auth or an assertion.


## Request token {#requestoauthtoken}

Request an OAuth access token with Basic Auth or an assertion. When making a request with an assertion, do not provide the Basic Auth header. See also [OAuth 2.0](/docs/guides/getting-started/developers/api-security/#oauth-20) in the *Airship API Security* documentation.

Use `oauth2.asnapius.com` for Airship's North American cloud site and `oauth2.asnapieu.com` for Airship's European cloud site when requesting an OAuth token.

[Jump to examples ↓](#requestoauthtoken-examples)

### `POST /token`

{{< note >}}
When using the OAuth token for Airship API endpoints, make sure your requests are using the appropriate [domain in the base URL](/docs/developer/rest-api/ua/introduction/#servers).

This example uses the OAuth token to list channels on Airship's North American cloud site: {{< highlight "bash" >}} curl --location 'https://api.asnapius.com/api/channels/' \
 --header 'Accept: application/vnd.urbanairship+json; version=3;' \
 --header 'Authorization: Bearer {OAUTH_ACCESS_TOKEN}'
{{< /highlight >}}


{{< /note >}}

**Security:**

- [basicOauth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicOauth)

**Request headers:**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `Content-Type` | `string` | Required | The request must have a `Content-Type` of `application/x-www-form-urlencoded`. |

**Request body**

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

**One of:**

  - **`grant_type`** `string` **REQUIRED**

    Possible values: `client_credentials`

  - **`ipaddr`** `string`

    A list of CIDR representations of valid IP addresses to which the issued token is restricted. IP addresses can be sent as a URL-encoded, space-delimited list (example: `ipaddr=24.20.40.0%2F24%202001%3A4860%3A4860%3A%3A8888%2F32`) or as a list as expected in a query parameter form (example: `ipaddr=24.20.40.0/24&ipaddr=2001:4860:4860::8888/32`).

  - **`scope`** `string` <[OAuth Scope]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#oauthscope)>

    A list of scopes to which the issued token will be entitled. Scopes can be sent as URL-encoded, space-delimited list (example: `scope=chn%20nu`) or as a list as expected in a query parameter form (example: `scope=chn&scope=nu`).

    The value of the scope parameter is a list of space-delimited, case-sensitive strings. If multiple scopes are specified, their order does not matter. Each string adds an additional access range to the requested scope. For more information about scope values, see [OAuth token scopes](/docs/developer/rest-api/ua/api-auth-reference/#oauth-token-scopes) in the *Airship API Authorization Reference* documentation.
  * `att`: Attachments
  * `chn`: Channels
  * `tpl`: Content
  * `evt`: Events
  * `lst`: Lists
  * `nu`: Named Users
  * `pln`: Pipelines
  * `psh`: Push
  * `sch`: Schedules

    Possible values: `att`, `chn`, `tpl`, `evt`, `lst`, `nu`, `pln`, `psh`, `sch`

  - **`sub`** `object` <[Subject]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#subject)> **REQUIRED**

    A space-delimited set of identifiers for which subjects a token is allowed. An `app` subject is required. Example: `app:JQIMcndxIHWy2QISpt1SpZ`.

    A space-delimited set of identifiers for which subjects a token is allowed. Example: `app:JQIMcndxIHWy2QISpt1SpZ`
  * `app`: May operate on the given app

  - **`assertion`** `object` <[Assertion JWT]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#assertionjwt)> **REQUIRED**

    An encoded JWT that contains the required headers and claims and is signed with the client credentials' private key.

    A JSON Web Token (JWT) used for authorization in [OAuth token requests](/docs/developer/rest-api/ua/operations/oauth/#requestoauthtoken). The JWT must be signed with the private key corresponding to the `client_id` in the `kid` header using the ES384 algorithm.

  - **`grant_type`** `string` **REQUIRED**

    Possible values: `client_credentials`


**Responses**

**`200`** Returned on token request success.

Response headers:

| Name | Type | Description |
|------|------|-------------|
| `Cache-Control` | `string` |  Possible values: `no-store` |
| `Content-Type` | `string` |  Possible values: `application/json` |
| `Pragma` | `string` |  Possible values: `no-cache` |

Response body:

**Content-Type:** `application/json`

- **`access_token`** `string`

  The issued token that can be used for all endpoints as allowed by set scopes.

- **`expires_in`** `integer`

  The number of seconds from the time the token is generated until it expires.

- **`scope`** `string` <[OAuth Scope]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#oauthscope)>

  A space-delimited list of scopes of the issued token. There may be undocumented scopes in this list.

  The value of the scope parameter is a list of space-delimited, case-sensitive strings. If multiple scopes are specified, their order does not matter. Each string adds an additional access range to the requested scope. For more information about scope values, see [OAuth token scopes](/docs/developer/rest-api/ua/api-auth-reference/#oauth-token-scopes) in the *Airship API Authorization Reference* documentation.
  * `att`: Attachments
  * `chn`: Channels
  * `tpl`: Content
  * `evt`: Events
  * `lst`: Lists
  * `nu`: Named Users
  * `pln`: Pipelines
  * `psh`: Push
  * `sch`: Schedules

  Possible values: `att`, `chn`, `tpl`, `evt`, `lst`, `nu`, `pln`, `psh`, `sch`

- **`token_type`** `string`

  The type of issued token.

  Possible values: `Bearer`

**`400`** Token not generated.

Response body:

**Content-Type:** `application/json`

- **`error`** `string` **REQUIRED**

  Error code.

  Possible values: `invalid_scope`, `invalid_request`, `invalid_grant`, `unauthorized_client`, `unsupported_grant_type`, `invalid_client`

- **`error_description`** `string`

  A plain-text description of the error.

**`401`** Unauthorized.

Response headers:

| Name | Type | Description |
|------|------|-------------|
| `WWW-Authenticate` | `string` | The HTTP authentication methods that can be used to request an access token. |

Response body:

**Content-Type:** `application/json`

- **`error`** `string` **REQUIRED**

  Error code.

  Possible values: `invalid_client`

- **`error_description`** `string`

  A plain-text description of the error.

**`406`** Not acceptable.

Response body:

**Content-Type:** `application/json`

- **`error`** `string` **REQUIRED**

  Error code.

  Possible values: `invalid_request`

- **`error_description`** `string`

  A plain-text description of the error.

**Examples**

*Example request token with Basic Auth*

```http
POST /token HTTP/1.1
Host: oauth2.asnapius.com
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Authorization: Basic <base64 encoded string of "client_id:client_secret">

grant_type=client_credentials&sub=app:JQIMcndxIHWy2QISpt1SpZ&scope=chn&scope=nu&ipaddr=24.20.40.0/24&ipaddr=2001:4860:4860::8888/32

```

```http
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "access_token": "<token>",
  "token_type": "Bearer",
  "scope": "chn nu",
  "expires_in": 3600
}

```

```java
OAuthCredentials oAuthCredentials = OAuthCredentials.newBuilder("<client_id>")
        .setClientSecret("<client_secret>")
        .setSub("<sub>")
        .setScopes(Arrays.asList("<scope1>","<scope2>","<...>"))
        .setIpAddresses(Arrays.asList("<IP1>","<IP2>",<...>))
        .build();

UrbanAirshipClient oAuthClient = UrbanAirshipClient.newBuilder()
        .setKey("yourAppKey")
        .setOAuthCredentials(oAuthCredentials)
        .build();

```

*Example request token with assertion*

```http
POST /token HTTP/1.1
Host: oauth2.asnapius.com
Content-Type: application/x-www-form-urlencoded
Accept: application/json

grant_type=client_credentials&assertion=<encoded_jwt>

```

```http
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "access_token": "<token>",
  "token_type": "Bearer",
  "scope": "chn nu",
  "expires_in": 3600
}

```

```java
OAuthCredentials oAuthCredentials = OAuthCredentials.newBuilder("<client_id>")
        .setAssertionJWT("<encoded_jwt>")
        .build();

UrbanAirshipClient oAuthClient = UrbanAirshipClient.newBuilder()
        .setKey("<app key>")
        .setOAuthCredentials(oAuthCredentials)
        .build();

```

```python
# The python OAuth client handles JWT creation 
# and token refresh automatically.
# Once instantiated, this can be used as any other Airship client.

airship_client = OAuthClient(
  client_id="<client_id>",
  private_key="<private_key>",
  key="<project_key>",
  scope=["<scopes>",],
  id_addr=["<ip list>",],
  timeout="<timeout seconds int>",
  retries="<attempts on failure int>"
)

```

```ruby
require 'urbanairship'

UA = Urbanairship
app_key = '<application_key>'

oauth = UA::Oauth.new(
  client_id: '<client_id>',
  key: app_key,
  assertion_private_key: '<your_private_key>',
  scopes: ['psh', 'chn'], # Optional
  ip_addresses: ['23.74.131.15/22'], # Optional
  oauth_server: 'api.asnapieu.com' # Optional
)

airship = UA::Client.new(key: app_key, oauth: oauth)

```

---

## Verify public key {#getkeyverification}

Retrieve the public key of a key ID. Use `oauth2.asnapius.com` for Airship's North American cloud site and `oauth2.asnapieu.com` for Airship's European cloud site when verifying an OAuth public key.

[Jump to examples ↓](#getkeyverification-examples)

### `GET /verify/public_key/{kid}`

**Path parameters:**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `kid` | `string` | Required | The private key ID used to sign the token. Example: `8817e96` |

**Responses**

**`200`** Returned on success with the public key for the given `kid`.

Response headers:

| Name | Type | Description |
|------|------|-------------|
| `Cache-Control` | `string` | The response contains a `Cache-Control` header which must be respected. |

Response body:

**Content-Type:** `application/x-pem-file`

Type: `string`

**`404`** The requested resource doesn't exist.

Response body:

**Content-Type:** `application/json`

Type: `object`

**Examples**

*Example verify public key*

```http
GET /verify/public_key/8817e96 HTTP/1.1
Host: oauth2.asnapius.com
Accept: text/plain

```

```http
HTTP/1.1 200 OK
Content-Type: application/x-pem-file
Cache-Control: max-age=600, must-revalidate

-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7tcTz03ypC7PSPa73Cbgl7AbDDo+92eH
DWgjAi6vt1gmlHE35e+GhpcwbywBByOiooY+5bvfUHkc0aKy4R8VbBK0rYwlp8B+
fxyDr9Ye/oiUewMwwlp0z5AMPjgBUIKS
-----END PUBLIC KEY-----

```

```java
UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
        .setKey("<app key>")
        .setSecret("<master secret>")
        .build();

PublicKeyVerificationRequest request = PublicKeyVerificationRequest.newRequest("<kid>");
Response<String> response = client.execute(request);

```

```ruby
require 'urbanairship'

UA = Urbanairship
app_key = '<application_key>'

oauth = UA::Oauth.new(
  client_id: '<client_id>',
  key: app_key,
  assertion_private_key: '<your_private_key>',
  scopes: ['psh', 'chn'], # Optional
  ip_addresses: ['23.74.131.15/22'], # Optional
  oauth_server: 'api.asnapieu.com' # Optional
)

public_key = oauth.verify_public_key('<key_id>')

```

---

