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

# Authentication (Developer Reference)

> Implementation-level reference for OAuth + PKCE and API key authentication. See Usage / Authentication for the user-facing guide.

This page is the developer-reference companion to [Usage / Authentication](/usage-auth). It documents the exact endpoint shapes, header names, error codes, and edge cases.

## Endpoint summary

| Endpoint                      | Method | Purpose                                                 |
| ----------------------------- | ------ | ------------------------------------------------------- |
| `GET /v1/auth/authorize`      | GET    | OAuth authorization endpoint (browser redirect)         |
| `POST /v1/auth/token`         | POST   | `AuthService.ExchangeToken` — code → tokens             |
| `POST /v1/auth/token/refresh` | POST   | `AuthService.RefreshToken` — refresh → new access token |
| `POST /v1/auth/token/revoke`  | POST   | `AuthService.RevokeToken` — invalidate a token          |

## Headers

| Header          | Format                  | Used by                      |
| --------------- | ----------------------- | ---------------------------- |
| `Authorization` | `Bearer <access_token>` | OAuth-authenticated requests |
| `x-api-key`     | `<api_key_secret>`      | API-key requests             |
| `Content-Type`  | `application/json`      | Every request body           |

Pass **either** `Authorization` or `x-api-key`, never both. Sending both returns `ERROR_CODE_INVALID_REQUEST`.

## OAuth — wire-level

### Authorization request

```
GET /v1/auth/authorize
  ?client_id=...
  &redirect_uri=...
  &response_type=code
  &scope=read+stream
  &code_challenge=...
  &code_challenge_method=S256
  &state=...
```

`code_challenge_method=S256` is **required**. The legacy `plain` method is rejected.

### Token exchange

```http theme={null}
POST /v1/auth/token
Content-Type: application/json

{
  "grant_type": "authorization_code",
  "code": "...",
  "redirect_uri": "...",
  "client_id": "...",
  "code_verifier": "..."
}
```

Response:

```json theme={null}
{
  "access_token": "...",
  "refresh_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "read stream"
}
```

### Refresh

```http theme={null}
POST /v1/auth/token/refresh
Content-Type: application/json

{
  "refresh_token": "...",
  "client_id": "..."
}
```

The response **may rotate** the refresh token — always overwrite your stored value with the latest.

### Revoke

```http theme={null}
POST /v1/auth/token/revoke
Content-Type: application/json

{
  "token": "...",
  "token_type_hint": "access_token" | "refresh_token"
}
```

Idempotent. Revoking an already-revoked token returns success.

## Token introspection

`AuthService` includes `TokenInfo` for inspecting the active token's scopes and expiration when needed. See [`sdk/auth/v1/token_info.proto`](https://github.com/anghami/sdk/blob/main/sdk/auth/v1/token_info.proto).

## Edge cases

| Situation                                                  | What happens                                           |
| ---------------------------------------------------------- | ------------------------------------------------------ |
| Both `Authorization` and `x-api-key` sent                  | `ERROR_CODE_INVALID_REQUEST`                           |
| Expired access token                                       | `ERROR_CODE_UNAUTHENTICATED` — refresh and retry       |
| Refresh token used twice (after rotation)                  | `ERROR_CODE_UNAUTHENTICATED` — re-prompt user          |
| API-key request to a stream-acquire endpoint               | `ERROR_CODE_PERMISSION_DENIED` — wrong credential type |
| OAuth token without the `stream` scope on `Acquire*Stream` | `ERROR_CODE_PERMISSION_DENIED`                         |

## Related

* [Usage / Authentication](/usage-auth) — narrative walkthrough.
* [OAuth Scopes](/oauth-scopes) — what each scope grants.
* [API Keys](/api-keys) — server-to-server credential lifecycle.
* [Errors](/usage-errors) — error code reference.
