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

# Auth API

> Authentication, registration, and token management

# Auth API

All auth endpoints are under `/api/v1/auth`. Rate limit: **20 requests/minute**.

## Endpoints

| Method | Path                           | Auth     | Description                  |
| ------ | ------------------------------ | -------- | ---------------------------- |
| POST   | `/auth/register`               | Public   | Register a new user          |
| POST   | `/auth/login`                  | Public   | Login and get tokens         |
| POST   | `/auth/logout`                 | Required | Revoke refresh token         |
| POST   | `/auth/verify-email`           | Public   | Verify email address         |
| POST   | `/auth/password-reset/request` | Public   | Request password reset email |
| POST   | `/auth/password-reset/confirm` | Public   | Set new password             |
| POST   | `/auth/refresh`                | Public   | Rotate access token          |
| GET    | `/auth/google`                 | Public   | Initiate Google OAuth        |
| GET    | `/auth/google/callback`        | Public   | Google OAuth callback        |

***

## Register

Create a new user account. Sends a verification email.

```bash theme={null}
POST /auth/register
```

### Request Body

```json theme={null}
{
  "email": "user@example.com",
  "password": "Secure@123",
  "first_name": "John",
  "last_name": "Doe"
}
```

### Response `201 Created`

```json theme={null}
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "email": "user@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "email_verified": false,
  "created_at": "2024-01-15T10:30:00Z"
}
```

### Errors

| Status | Detail                                          |
| ------ | ----------------------------------------------- |
| `409`  | Email already registered                        |
| `422`  | Validation error (invalid email, weak password) |

***

## Login

Authenticate and receive JWT access + refresh tokens.

```bash theme={null}
POST /auth/login
```

### Request Body

```json theme={null}
{
  "email": "user@example.com",
  "password": "Secure@123"
}
```

### Response `200 OK`

```json theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "first_name": "John"
  }
}
```

### Token Expiry

| Token         | Lifetime   |
| ------------- | ---------- |
| Access token  | 60 minutes |
| Refresh token | 7 days     |

### Errors

| Status | Detail                    |
| ------ | ------------------------- |
| `401`  | Invalid email or password |
| `403`  | Email not verified        |

***

## Logout

Revoke the current refresh token (invalidates the session).

```bash theme={null}
POST /auth/logout
Authorization: Bearer <access_token>
```

### Response `200 OK`

```json theme={null}
{ "message": "Logged out successfully" }
```

***

## Verify Email

Confirm an email address using the token from the verification email.

```bash theme={null}
POST /auth/verify-email
```

### Request Body

```json theme={null}
{
  "token": "abc123verificationtoken"
}
```

### Response `200 OK`

```json theme={null}
{ "message": "Email verified successfully" }
```

### Errors

| Status | Detail                                |
| ------ | ------------------------------------- |
| `400`  | Invalid or expired verification token |

***

## Request Password Reset

Send a password reset email.

```bash theme={null}
POST /auth/password-reset/request
```

### Request Body

```json theme={null}
{
  "email": "user@example.com"
}
```

### Response `200 OK`

```json theme={null}
{ "message": "Password reset email sent" }
```

<Note>
  Always returns 200 even if the email is not registered (prevents user enumeration).
</Note>

***

## Confirm Password Reset

Set a new password using the token from the reset email.

```bash theme={null}
POST /auth/password-reset/confirm
```

### Request Body

```json theme={null}
{
  "token": "abc123resettoken",
  "new_password": "NewSecure@456"
}
```

### Response `200 OK`

```json theme={null}
{ "message": "Password reset successfully" }
```

### Errors

| Status | Detail                         |
| ------ | ------------------------------ |
| `400`  | Invalid or expired reset token |

***

## Refresh Token

Exchange a refresh token for a new access token. The refresh token is rotated on each use.

```bash theme={null}
POST /auth/refresh
```

### Request Body

```json theme={null}
{
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

### Response `200 OK`

```json theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}
```

<Note>
  Token rotation is enabled — each refresh invalidates the old refresh token and issues a new one.
</Note>

### Errors

| Status | Detail                           |
| ------ | -------------------------------- |
| `401`  | Invalid or expired refresh token |

***

## Google OAuth

Single sign-on via Google. Redirects through Google's consent screen and returns tokens on success.

### Step 1 — Initiate

Redirect the user's browser to:

```
GET /api/v1/auth/google
```

This redirects to Google's OAuth consent screen.

### Step 2 — Callback

After the user approves, Google redirects back to:

```
GET /api/v1/auth/google/callback?code=...
```

On success, the server redirects to the frontend with the access token:

```
/auth/callback?access_token=eyJhbGc...
```

The frontend (`AuthCallback` page) reads the token from the URL, fetches the user profile, and stores auth state.

### New vs Returning Users

* **New user** — account is auto-created with `auth_provider = "google"`, no password set
* **Returning user** — existing account is found by email and tokens are issued

***

## Using Tokens

Include the access token in the `Authorization` header for all protected endpoints:

```bash theme={null}
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

When the access token expires (60 min), call `POST /auth/refresh` to get a new one. The frontend Axios interceptor handles this automatically.
