> For the complete documentation index, see [llms.txt](https://docs.moodymusic.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.moodymusic.xyz/api-reference/authentication.md).

# Authentication

Moody Music uses **Discord OAuth2** for user authentication and issues signed JWT tokens for session management.

## Login Flow

1. **Redirect** the user to `/api/auth/login`
2. Discord asks the user to authorize with `identify guilds` scope
3. After authorization, Discord redirects to `/api/auth/discord/callback?code=...`
4. The backend exchanges the code for an access token, fetches user info, and creates/updates the user record
5. A **signed JWT** is issued (24-hour expiry) containing `discordId`, `username`, and `avatar`
6. The browser is redirected to the frontend dashboard with the JWT as a query parameter

## Endpoints

### GET /api/auth/login

Redirects the user to Discord's OAuth2 authorization page.

::: details Response 302 Redirect to `https://discord.com/api/oauth2/authorize?...` :::

### GET /api/auth/discord/callback

Handles the OAuth2 callback from Discord.

**Query Parameters:**

| Parameter | Description                              |
| --------- | ---------------------------------------- |
| `code`    | Authorization code from Discord          |
| `state`   | CSRF state token (validated server-side) |

**Redirects to:** `FRONTEND_URL/dashboard?token=<jwt>&discordId=<id>&username=<name>&avatar=<url>&isPremium=<bool>`

### GET /api/auth/user/:discordId

Returns live premium status for a user.

**Response:**

```json
{
  "isPremium": true,
  "premiumExpiresAt": "2026-12-31T23:59:59.000Z"
}
```

## Security

* OAuth2 state parameter is generated via `crypto.randomBytes(16)` with a 5-minute TTL
* Discord `access_token` is never exposed to the frontend — replaced with a signed JWT
* JWT is signed with `JWT_SECRET` and expires in 24 hours
