> ## Documentation Index
> Fetch the complete documentation index at: https://docs.taxrock.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> OAuth 2.0 Authorization Code with PKCE, refresh tokens, and reconnects.

The Delegate API uses OAuth 2.0 **Authorization Code with PKCE**. Your backend ends up
holding a long-lived **refresh token** per end-user, which it exchanges for short-lived
**access tokens** to call the API. See the [Quickstart](/quickstart) for the concrete
commands; this page covers the model and steady-state behavior.

## The flow

<Steps>
  <Step title="Authorize (one-time, interactive)">
    Send the user to the `/authorize` URL. They log in to TaxRock and consent to
    `read:client-accounts`, and TaxRock redirects to your registered callback with
    `?code=...`. Generate the `code_challenge` from a `code_verifier` (PKCE, S256) and
    keep the verifier for the next step.
  </Step>

  <Step title="Exchange the code (backend)">
    POST the `code`, `code_verifier`, and `client_secret` to the token endpoint to
    receive an `access_token` and a `refresh_token`. **Store the refresh token securely,
    per end-user.**
  </Step>

  <Step title="Refresh (steady state)">
    When a cached access token has expired, exchange the refresh token for a fresh
    access token.
  </Step>
</Steps>

## Tokens

* **Access token** — short-lived, about an hour. Cache and reuse it rather than minting
  one per request. Send it as a `Bearer` credential.
* **Refresh token** — non-rotating, so keep using the same one; the refresh response
  returns no new refresh token. It expires after about **100 days idle**, with an
  absolute maximum lifetime of about **365 days**, after which the user must reconnect
  even if active.
* **`audience`** — an access token is only valid for the audience it was requested for,
  so include `audience` on the refresh call.

```bash Refresh theme={null}
curl -X POST https://login-demo.taxrock.com/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "refresh_token",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "refresh_token": "YOUR_REFRESH_TOKEN",
    "audience": "https://delegate.api.taxrock.com"
  }'
```

## When a user must reconnect

A refresh that returns `invalid_grant`, or an API response of `401`, means that user's
connection is broken. `invalid_grant` happens when the refresh token expired: it sat
idle past \~100 days, reached its \~365-day maximum, or was revoked. Send the user back
through the authorize step and surface a **"Reconnect TaxRock"** action. This is normal
steady-state behavior, not an error to alarm the user with.

A `403` from the API is different: the connected user lacks the required permission,
which re-consent will not fix, so treat it as a configuration issue rather than a
reconnect.

<Note>
  We will give advance notice if a change ever requires re-consent (for example, a new
  scope). Watch the [Changelog](/changelog).
</Note>

## PKCE

For more on generating the `code_challenge` and `code_verifier`, see
[RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636).
