# Authentication (/docs/agents/authentication)

The MCP server and the REST API accept the same two credentials, both sent as a
bearer token:

| Credential | Best for | Acts as |
| --- | --- | --- |
| OAuth access token | AI agents and apps that people sign in to | The person who approved access, in the team they chose |
| Team API key | Scripts, scheduled jobs, and clients without OAuth | The member who created the key, in that key's team |

## OAuth [#oauth]

Osorik is an OAuth 2.1 authorization server with dynamic client registration.
Most MCP clients handle every step on their own; this section is for people
building a client.

### Discovery [#discovery]

| Metadata | URL |
| --- | --- |
| Protected resource ([RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728)) | `https://api.osorik.dev/.well-known/oauth-protected-resource/mcp` |
| Authorization server ([RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414)) | `https://api.osorik.dev/.well-known/oauth-authorization-server/api/auth` |

The authorization server's issuer is `https://api.osorik.dev/api/auth`. Use RFC 8414
discovery; `/.well-known/openid-configuration` describes a different issuer.

### Scopes [#scopes]

| Scope | Grants |
| --- | --- |
| `read` | Every read operation: `GET` routes and read-only tools |
| `write` | Every operation that creates, changes or deletes data |
| `offline_access` | A refresh token, so the client can stay signed in |

`write` does not include `read`; most clients request both. Requesting any
other scope, such as `openid`, fails with `invalid_scope`.
Without `offline_access`, the client must sign in again when the access token
expires after one hour.

### Requests [#requests]

- Register clients as public clients. Registration always returns
  `token_endpoint_auth_method: none`, whatever the request asks for.
- Send `resource=https://api.osorik.dev/mcp` exactly, with no trailing slash. The token
  endpoint rejects any other value.
- Sign-in and consent happen at `https://app.osorik.dev/oauth/authorize`, where the person
  picks the team the client will act in.

## API keys [#api-keys]

A team API key starts with `osk_` and belongs to one member in one team.

1. In Osorik, open the team menu at the bottom of the sidebar, choose
   **Team**, then open the **API keys** tab.
2. Choose **Create key** and give it a name that says where it's used, such
   as _Accounting export_.
3. Pick its access: **Read only** keys get the `read` scope, **Read and
   write** keys get `read` and `write`.
4. Copy the key and store it in a secret manager or environment variable.

Anyone with the key has the access of the member who created it, so treat it
like a password. Members can revoke their own keys. Owners and admins can see
and revoke every member's keys.

Send the key on every request:

```http
Authorization: Bearer osk_…
```
