# Authentication

## Public or signed in

Most of the API is public and needs nothing. Endpoints that act for a person need a bearer token in the `Authorization` header:

```http
GET /v1/me HTTP/1.1
Host: api.alloymc.dev
Authorization: Bearer <token>
```

Without a valid token they answer `401` with the code `unauthorized`. The [reference](https://api.alloymc.dev/docs/reference) marks these endpoints with **token**.

Tokens are never put in cookies or URLs, so they can't leak through links or other sites.

## Who can get a token today

Right now only Alloy, the launcher, can sign people in and receive tokens. The flow below is documented so you can see exactly what happens with your account. Apps of your own, with their own consent screen and limited scopes, are the [next thing on the developer roadmap](https://api.alloymc.dev/docs/roadmap#apps-and-scopes).

## How Alloy signs you in

Alloy uses a one-time code with [PKCE](https://www.rfc-editor.org/rfc/rfc7636), the same idea OAuth uses for apps that can't keep a secret. Your password is only ever typed on alloymc.dev, never into Alloy.

1. **Alloy makes a secret.** It creates a random `verifier` and its SHA-256 hash, the `challenge`, encoded as base64url without padding.
2. **Alloy opens your browser** at `https://alloymc.dev/auth/app?challenge=<challenge>&state=<random>&device=<name>`. You sign in there if needed and see who's asking, for example "Alloy on Sam's PC".
3. **You choose Allow.** The browser hands a one-time `code` back to Alloy through `alloy://auth?code=<code>&state=<state>`. Alloy checks that `state` is the one it sent.
4. **Alloy trades the code for a token**, proving it made the challenge:

```bash
curl -X POST https://api.alloymc.dev/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{"code": "<code>", "verifier": "<verifier>"}'
```

```json
{
  "token": "<token>",
  "tokenType": "Bearer",
  "user": { "handle": "kestrel", "displayName": "Kestrel" }
}
```

A code works once, for a few minutes, and only with the matching verifier. Someone who intercepts the redirect can't use it.

## How long tokens last

A token stays valid while it's used and ends after **90 days without use**. You can see every signed-in device on your [account page](https://alloymc.dev/account#devices) and sign any of them out. Changing your password signs out everything else.

To sign a token out from the app itself:

```bash
curl -X DELETE https://api.alloymc.dev/v1/auth/token -H "Authorization: Bearer <token>"
```

## Keeping tokens safe

- Store tokens where the operating system protects them, like the system keychain.
- Send them only to `https://api.alloymc.dev`.
- If a token leaks, sign it out under Devices. Found a security problem? Write to [security@elchi.dev](mailto:security@elchi.dev).
