# Tokens
Done ID issues JSON Web Tokens (JWT) signed with RS256. This page tells you what the tokens contain, how long they live, and how to validate them.

## Lifetimes

| Item | Lifetime |
|---|---|
| Access token | 5 minutes |
| Done ID session without activity | 30 minutes |
| Done ID session, maximum | 10 hours |

A refresh token stays valid while the Done ID session is active. When the session ends, the user must sign in again.

Use the `expires_in` value of the token response. Do not hard-code the lifetime, because it can change.

## Validate a token

If your API receives Done ID tokens, validate each token before you use it:

1. Get the signing keys from `<issuer>/protocol/openid-connect/certs`. Cache the keys and get them again when a token has an unknown `kid`.
2. Make sure that the signature is correct and that the algorithm is `RS256`.
3. Make sure that `iss` is the issuer of the environment, for example `https://id.done.ai/realms/done`.
4. Make sure that `aud` contains the audience of your API.
5. Make sure that `exp` is in the future.

Most JWT libraries do these steps when you give them the issuer and the audience.

A client with a secret can also send the token to `<issuer>/protocol/openid-connect/token/introspect`. Done ID returns `"active": true` and the claims if the token is valid. Introspection also detects a token from a session that ended, but each call is a network request. Use local validation for each request, and introspection only when you must know that the session is still active.

## User tokens

A user token comes from the user login flow. These are the claims that your app usually needs:

| Claim | Token | Description |
|---|---|---|
| `sub` | ID, access | The ID of the user in Done ID. It does not change. |
| `email` | ID, access | Email address. Needs the `email` scope. |
| `email_verified` | ID, access | `true` if the user confirmed the email address. |
| `name`, `given_name`, `family_name` | ID, access | Name. Needs the `profile` scope. |
| `azp` | ID, access | The client ID of the app that requested the token. |
| `acr` | ID, access | The authentication level of the login: `urn:done:acr:basic` or `urn:done:acr:strong`. |
| `legal_entity_id` | ID, access | The selected company or person. Needs a `legal-entity.*` scope. |
| `legal_entity_name` | ID, access | The name of the selected company or person. |
| `legal_entity_type` | ID, access | The type of the selected legal entity. |

Use `sub` to identify the user. Do not use the email address, because the user can change it.

## Machine-to-machine tokens

A machine-to-machine token comes from the client credentials flow. It has no user.

| Claim | Description |
|---|---|
| `client_id` | Your client ID. |
| `azp` | Your client ID. |
| `partner_id` | The ID of your company in Done OS. The Done OS API uses it to find your data. |
| `aud` | Contains `partner-api`. |
| `realm_access.roles` | Contains `partner-api`. |

## Example: decode a token

Use this command to read the claims of a token while you test. It does not validate the signature.

```bash
echo "$ACCESS_TOKEN" | cut -d. -f2 | tr '_-' '/+' | base64 -d 2>/dev/null | jq
```

Do not paste production tokens into public websites that decode JWTs.

## See also

- [Done ID for partner apps](/)
