Skip to content

Authentication API

The Authentication API manages user registration, login, token lifecycle, and session management. Carbon Connect uses JWT Bearer tokens with separate access and refresh tokens.

JWT Flow

sequenceDiagram
    participant Client
    participant API as Carbon Connect API
    participant DB as Database

    Client->>API: POST /auth/register (email, password, name)
    API->>DB: Create user + tenant
    DB-->>API: User record
    API-->>Client: 201 UserResponse

    Client->>API: POST /auth/login (email, password)
    API->>DB: Verify credentials
    DB-->>API: User record
    API-->>Client: 200 Token (access + refresh)

    Client->>API: GET /auth/me (Bearer token)
    API->>API: Validate JWT
    API-->>Client: 200 UserResponse

    Note over Client,API: Access token expires (30 min)

    Client->>API: POST /auth/refresh (refresh_token)
    API->>API: Validate + blacklist old refresh
    API-->>Client: 200 New Token pair

    Client->>API: POST /auth/logout (Bearer token)
    API->>API: Blacklist token
    API-->>Client: 200 Success

Token Format

Tokens are signed JWTs containing the following claims:

Claim Type Description
sub string User email address
tenant_id string UUID of the user's tenant organization
exp int Expiration timestamp (Unix epoch)
type string Token type: "access" or "refresh"

Token lifetimes:

  • Access token: 30 minutes
  • Refresh token: 7 days

Password Requirements

Passwords must satisfy all of the following:

  • Minimum 8 characters
  • At least one uppercase letter (A-Z)
  • At least one lowercase letter (a-z)
  • At least one digit (0-9)
  • At least one special character (!@#$%^&*(),.?":{}|<>)

Passwords are hashed using bcrypt via passlib before storage.


Endpoints

POST /auth/register

Register a new user account with automatic tenant creation.

Authentication: None

{
  "email": "user@example.com",
  "password": "SecureP@ss1",
  "full_name": "Jane Smith"
}
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "email": "user@example.com",
  "full_name": "Jane Smith",
  "tenant_id": "660e8400-e29b-41d4-a716-446655440000",
  "role": "owner",
  "is_active": true,
  "email_verified": false,
  "created_at": "2025-01-15T10:30:00Z"
}
curl -X POST https://api.carbonconnect.io/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "SecureP@ss1",
    "full_name": "Jane Smith"
  }'

Request Body:

Field Type Required Description
email string Yes Valid email address
password string Yes Min 8 chars, must meet strength rules
full_name string Yes User display name (1-255 chars)

Status Codes:

Code Description
201 User created successfully
400 Email already registered or validation failed
422 Request body validation error

POST /auth/login

Authenticate and obtain access and refresh tokens. Uses OAuth2 password flow.

Authentication: None

OAuth2 Form Data

This endpoint uses application/x-www-form-urlencoded encoding (OAuth2 password flow). The username field contains the user's email address.

Content-Type: application/x-www-form-urlencoded

username=user@example.com&password=SecureP@ss1
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}
curl -X POST https://api.carbonconnect.io/api/v1/auth/login \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=user@example.com&password=SecureP@ss1"

Request Body (form-encoded):

Field Type Required Description
username string Yes User email address
password string Yes User password

Response Body:

Field Type Description
access_token string JWT access token (30 min)
refresh_token string JWT refresh token (7 days)
token_type string Always "bearer"

Status Codes:

Code Description
200 Login successful
401 Incorrect email or password
422 Request validation error

POST /auth/refresh

Exchange a valid refresh token for a new token pair. The old refresh token is blacklisted.

Authentication: None (uses refresh token in body)

{
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}
curl -X POST https://api.carbonconnect.io/api/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}'

Request Body:

Field Type Required Description
refresh_token string Yes Valid, non-blacklisted JWT

Single-Use Refresh Tokens

Refresh tokens are single-use. After a successful refresh, the old token is blacklisted and cannot be reused. This prevents token replay attacks.

Status Codes:

Code Description
200 New token pair issued
401 Invalid, expired, or blacklisted refresh token

GET /auth/me

Retrieve the current authenticated user's profile information.

Authentication: Required (Bearer token)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "email": "user@example.com",
  "full_name": "Jane Smith",
  "tenant_id": "660e8400-e29b-41d4-a716-446655440000",
  "role": "owner",
  "is_active": true,
  "email_verified": false,
  "created_at": "2025-01-15T10:30:00Z"
}
curl -X GET https://api.carbonconnect.io/api/v1/auth/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Response Body (UserResponse):

Field Type Description
id UUID User ID
email string User email address
full_name string Display name
tenant_id UUID Tenant organization ID
role string User role (owner, admin, member)
is_active boolean Whether the account is active
email_verified boolean Whether email has been verified
created_at string ISO 8601 creation timestamp

Status Codes:

Code Description
200 User info returned
401 Missing or invalid token

POST /auth/logout

Invalidate the current access token by adding it to the blacklist.

Authentication: Required (Bearer token)

{
  "message": "Successfully logged out"
}
curl -X POST https://api.carbonconnect.io/api/v1/auth/logout \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Status Codes:

Code Description
200 Token blacklisted
401 Missing or invalid token

Best Practice

After logout, discard both the access and refresh tokens on the client side. The blacklisted access token will be rejected on any subsequent request.