> For the complete documentation index, see [llms.txt](https://docs.tiny.plus/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tiny.plus/api/getting-access/oauth-authorisation-process.md).

# oAuth Authorisation process

We use OAuth 2.0, with the authorisation code flow and PKCE.

Once your app has a client ID (see [Register a Client App](/api/getting-access/register-a-client-app.md)), it gets an access token for each person who uses it:

1. Your app sends the person to tiny+ to sign in and approve it.
2. tiny+ sends them back to your app with a code.
3. Your app exchanges the code for an access token and a refresh token.

Apps must use PKCE ([RFC 7636](https://www.rfc-editor.org/rfc/rfc7636)) with the `S256` method. Apps that registered themselves are required to, and we recommend it for every app. Before step 1:

* make a random `code_verifier` of 43 to 128 characters;
* make its `code_challenge`: the SHA-256 hash of the verifier, base64url-encoded, without padding.

## 1. Send the person to sign in

<mark style="color:blue;">`GET`</mark> `https://login.tiny.plus/oauth/authorize`

#### Query Parameters

| Name                    | Type   | Description                                                                                                               |
| ----------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------- |
| response\_type          | string | Set this to `code`.                                                                                                       |
| client\_id              | string | Your app's `client_id`.                                                                                                   |
| redirect\_uri           | string | One of the redirect URIs your app registered.                                                                             |
| scope                   | string | `read`, or `read readwrite` if your app needs to add and change records. Default `read`.                                  |
| state                   | string | A random value that your app checks when the person comes back. This protects your users from cross-site request forgery. |
| code\_challenge         | string | The challenge you made from your code verifier.                                                                           |
| code\_challenge\_method | string | Set this to `S256`.                                                                                                       |

The person signs in, with single sign-on and two-factor authentication if their account uses them. They then see which app is asking, and what it wants to do. If your app asked for `readwrite`, there is a box they can tick to let it add and change records. If they don't tick it, your app's token can only read.

`https://api.tiny.plus/oauth/authorize` also works, and forwards to the address above.

## 2. The person comes back

When the person confirms, tiny+ sends them to your redirect URI with a code:

```
https://app.example.com/tiny/callback?code={{code}}&state={{state}}
```

Check that `state` matches the value you sent. The code lasts 10 minutes and can be used once.

If the person cancels, the redirect carries `error=access_denied` instead of a code.

## 3. Exchange the code for tokens

<mark style="color:green;">`POST`</mark> `https://api.tiny.plus/oauth/access_token`

#### Request Body

Send the body form-encoded (`application/x-www-form-urlencoded`):

| Name           | Type   | Description                               |
| -------------- | ------ | ----------------------------------------- |
| grant\_type    | string | Set this to `authorization_code`.         |
| client\_id     | string | Your app's `client_id`.                   |
| redirect\_uri  | string | The same redirect URI you used in step 1. |
| code           | string | The code from step 2.                     |
| code\_verifier | string | The code verifier you made at the start.  |

{% tabs %}
{% tab title="200 The person's tokens." %}

```javascript
{
    "token_type": "Bearer",
    "expires_in": 3600,
    "access_token": "{{access_token}}",
    "refresh_token": "{{refresh_token}}"
}
```

{% endtab %}
{% endtabs %}

Send the access token in the `Authorization` header of your API requests, as `Bearer {{access_token}}`. The access token lasts an hour, and the refresh token a month.

## Refreshing an access token

When the access token expires, get a new one with the refresh token:

<mark style="color:green;">`POST`</mark> `https://api.tiny.plus/oauth/access_token`

| Name           | Type   | Description                  |
| -------------- | ------ | ---------------------------- |
| grant\_type    | string | Set this to `refresh_token`. |
| client\_id     | string | Your app's `client_id`.      |
| refresh\_token | string | The refresh token.           |

The response has the same shape as in step 3. It includes a new refresh token, and the old one stops working, so store the new one each time.

## Scopes

| Scope       | Allows your app to                                                                                |
| ----------- | ------------------------------------------------------------------------------------------------- |
| `read`      | Read the person's tiny+ data.                                                                     |
| `readwrite` | Also add and change records. Only granted if the person ticks the box when they approve your app. |

A token acts as the person who approved your app, and can only see and change what they can. People can withdraw your app's access at any time, under their user settings, **External apps**.

## Older apps: the implicit flow

Some older apps use the implicit flow (`response_type=token`), which returns an access token straight away with no code to exchange. It is only available to apps we have enabled it for, and new apps can't use it.

The token comes back in the fragment of the redirect URI, not in the query string:

```
https://[yoururl]#access_token=[your access token]&token_type=Bearer&expires_in=[TTL]&state=[your provided CSRF token]
```

Implicit-flow tokens last a month and can't be refreshed.
