Skip to content

Authentication

Token Configuration

Token Expiry Storage
access_token 15 minutes Memory + Secure storage
refresh_token 7 days Secure storage (rotated on use)

Auth Header

All authenticated endpoints require:

Authorization: Bearer <access_token>

Authentication Endpoints

Register

POST /api/v1/auth/register
Content-Type: application/json

Request:
{
  "email": "user@example.com",
  "password": "securePassword123",
  "tenant_name": "Company Name"
}

Response (201):
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "is_active": true,
    "tenant_id": "660e8400-e29b-41d4-a716-446655440000"
  }
}

Login

POST /api/v1/auth/login
Content-Type: application/json

Request:
{
  "email": "user@example.com",
  "password": "securePassword123"
}

Response (200):
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "is_active": true,
    "tenant_id": "660e8400-e29b-41d4-a716-446655440000"
  }
}

Refresh Token

POST /api/v1/auth/refresh
Content-Type: application/json

Request:
{
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response (200):
{
  "access_token": "new_access_token...",
  "refresh_token": "new_refresh_token...",
  "token_type": "bearer"
}

Logout

POST /api/v1/auth/logout
Content-Type: application/json

Request:
{
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response (200):
{
  "message": "Logged out successfully"
}

Email Verification

Send Verification

POST /auth/email/send-verification
Content-Type: application/json

Request:
{
  "email": "user@example.com"
}

Response (200):
{
  "message": "Verification code sent"
}

Verify Email

POST /auth/email/verify
Content-Type: application/json

Request:
{
  "email": "user@example.com",
  "code": "123456"
}

Response (200):
{
  "message": "Email verified successfully"
}

Password Reset

Send Reset Email

POST /auth/email/send-reset-password
Content-Type: application/json

Request:
{
  "email": "user@example.com"
}

Response (200):
{
  "message": "If the email exists, a reset code has been sent"
}

Reset Password

POST /auth/email/reset-password
Content-Type: application/json

Request:
{
  "email": "user@example.com",
  "code": "123456",
  "new_password": "newSecurePassword456"
}

Response (200):
{
  "message": "Password reset successfully"
}

OAuth Authentication

Initiate OAuth

GET /api/v1/auth/oauth/google
GET /api/v1/auth/oauth/github

Response (200):
{
  "authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?...",
  "state": "random_state_string"
}

OAuth Callback

GET /api/v1/auth/oauth/google/callback?code=AUTHORIZATION_CODE&state=STATE

Response (200):
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "is_active": true,
    "tenant_id": "uuid"
  }
}

Supported Providers

Provider Endpoint
Google /api/v1/auth/oauth/google
GitHub /api/v1/auth/oauth/github
Custom (Okta) /api/v1/auth/oauth/custom/okta

Test Credentials

Role Email Password
Admin admin@courierflow.com admin
Courier courier@courierflow.com admin

Error Responses

401 Unauthorized

{
  "detail": "Invalid credentials"
}

400 Bad Request

{
  "detail": "User already exists"
}

422 Validation Error

{
  "detail": [
    {
      "loc": ["body", "email"],
      "msg": "value is not a valid email address",
      "type": "value_error.email"
    }
  ]
}

Security Considerations

  1. Password Storage: bcrypt with salt (never plaintext)
  2. Token Rotation: Refresh tokens rotate on every use
  3. JWT Payload: Contains sub (user_id), tenant_id, exp
  4. Rate Limits: Applied per endpoint (see Rate Limiting docs)