# 3.1 Authentication

JSONAir uses a two-token model. You authenticate with a long-lived **Personal Access Token (PAT)** to obtain a short-lived **JWT** (JSON Web Token). The JWT is then used as a Bearer token on all API requests.

***

## Step 1 — Exchange Your PAT for a JWT

**Endpoint:** `POST /api/v1/jsonair/auth/token`

**Request body:**

```json
{
  "token": "your-plain-text-pat"
}
```

**Successful response (200 OK):**

```json
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 3600
}
```

`expires_in` is the JWT lifetime in seconds. This is controlled by the server's `JWT_TOKEN_EXPIRE` environment variable (set in minutes, returned here as seconds).

**Failed response (401 Unauthorized):**

```json
{
  "error": "Session expired or invalid"
}
```

***

## Step 2 — Use the JWT on API Requests

Include the JWT in the `Authorization` header of every subsequent request:

```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

***

## Token Expiry and Re-Authentication

When a JWT expires, the API returns a `401`. Your client should catch this and repeat Step 1 to obtain a new JWT before retrying the original request.

***

## Rate Limiting

The `/auth/token` endpoint is rate limited to **5 requests per minute per IP address**. Exceeding this returns:

```
HTTP 429 Too Many Requests
```

```json
{
  "error": "Too many requests"
}
```

***

## Security Notes

* Your PAT is never stored in plain text. The server computes an HMAC-SHA256 hash of the PAT using the `TOKEN_HMAC_SECRET` and compares it against the hash stored in the database.
* The JWT is signed with HMAC-SHA256 using the server's `JWT_TOKEN_SECRET`. Tokens with unexpected signing methods or missing claims are rejected.
* Keep your PAT secure — treat it like a password. It should only ever appear in the agent's environment variables, never in source code or logs.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.k9.io/key9-identity/jsonair/3-using-the-api/3.1-authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
