Skip to main content
BookMe uses OAuth 2.0 authentication via 42 Intra, followed by JWT (JSON Web Token) based session management. This ensures secure access while maintaining stateless API operations.

Authentication Overview

The authentication process involves two main phases:
  1. OAuth 2.0 Flow - Initial authentication via 42 Intra
  2. JWT Token Management - Ongoing API authorization

OAuth 2.0 Flow

Step-by-Step Process

1

Initiate Login

User clicks “Login” and is redirected to /oauth/login
GET /oauth/login
The server generates a cryptographically secure state token (32 bytes, hex-encoded) and stores it in a session cookie for CSRF protection.
2

OAuth Provider Redirect

System redirects to 42 Intra OAuth provider with the authorization URL
https://api.intra.42.fr/oauth/authorize?client_id=...&state=...
3

User Authorization

User authorizes the application on the 42 Intra platform
4

OAuth Callback

OAuth provider redirects back to /oauth/callback with authorization code
GET /oauth/callback?code=AUTH_CODE&state=STATE_TOKEN
5

State Validation

Server validates the state token to prevent CSRF attacksSource: internal/oauth/service.go:97-114
If state validation fails, the request is rejected with 403 Forbidden error.
6

Token Exchange

System exchanges authorization code for access token with 42 Intra APISource: internal/oauth/provider42.go:63-70
7

Fetch User Info

System fetches user information from 42 Intra with retry logic:
  • Max Retries: 3
  • Retry Wait: 1-5 seconds with exponential backoff
  • Timeout: 15 seconds
Source: internal/oauth/provider42.go:73-111
The retry mechanism ensures reliability when communicating with the 42 Intra API.
8

Campus Validation

Verify user belongs to Hive Helsinki (Campus ID: 13)
// Only users with campus_id=13 as primary campus are allowed
isHive := false
for _, camp := range user42.Campus {
    if camp.ID == 13 && camp.Primary {
        isHive = true
        break
    }
}
Source: internal/oauth/service.go:75-84
Users from other campuses receive a 403 Forbidden error: “access denied: only helsinki campus student allowed”
9

Create/Update User

System finds existing user or creates a new database recordUser roles are determined by 42 Intra staff status:
  • staff? = trueStaff role
  • staff? = falseStudent role
Source: internal/oauth/provider42.go:128-160
10

Generate JWT Token

Server generates a JWT access token containing user informationToken Configuration:
  • Algorithm: HS256 (HMAC with SHA-256)
  • Expiration: 1 hour
  • Token Type: access
Source: internal/auth/auth.go:76-96
11

Return Token

JWT token is returned to the client and redirected to the configured URL

JWT Token Structure

The JWT token contains the following claims:
{
  "name": "John Doe",
  "role": "student",
  "sub": "42",
  "iss": "access",
  "iat": 1234567890,
  "exp": 1234571490
}

Custom Claims

ClaimDescriptionSource
nameUser’s login name from 42 Intrauser.Name
roleUser role: student or staffuser.Role
subUser ID (subject)user.ID
issToken issuer (always “access”)tokenTypeAccess
iatIssued at timestampCurrent time
expExpiration timestampCurrent time + 1 hour
Source: internal/auth/auth.go:20-25, internal/auth/auth.go:79-88

Using JWT Tokens

Making Authenticated Requests

Include the JWT token in the Authorization header with the Bearer scheme:
curl -X POST http://localhost:8080/api/v1/reservations \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "roomId": 1,
    "startTime": "2025-01-28T14:00:00Z",
    "endTime": "2025-01-28T16:00:00Z"
  }'

Token Validation

The server validates JWT tokens on protected endpoints:
  1. Extract Bearer Token from Authorization header
  2. Verify Signature using HS256 algorithm
  3. Check Expiration - Reject if expired
  4. Validate Claims - Ensure token type is “access”
  5. Extract User Info - Load user ID, name, and role into request context
Source: internal/auth/auth.go:99-125, internal/auth/auth.go:128-141
Tokens expire after 1 hour. Clients must handle token expiration and re-authenticate when necessary.

Error Responses

OAuth Errors

ErrorStatus CodeDescription
invalid or missing oauth code400Authorization code is missing or invalid
oauth state mismatch403CSRF protection - state token mismatch
access denied: only helsinki campus student allowed403User is not from Hive Helsinki campus
oauth request timeout504Request to 42 Intra API timed out
oauth token exchange failed500Failed to exchange code for token
failed to fetch user info from oauth provider500Failed to retrieve user data from 42
failed to find or create user500Database error during user creation
Source: internal/oauth/errors.go:40-81

JWT Authentication Errors

ErrorStatus CodeDescription
no auth header included in request401Missing Authorization header
bearer token is empty401Empty token after “Bearer ” prefix
bearer token is incorrect401Missing “Bearer ” prefix
invalid token401Token signature validation failed
expired token401Token has expired (> 1 hour old)
Source: internal/auth/auth.go:49-55
All authentication errors return JSON responses with an error field containing the error message.

Security Features

CSRF Protection

  • Cryptographically secure random state tokens (32 bytes)
  • State stored in HTTP-only session cookies
  • State validation on OAuth callback
Source: internal/oauth/service.go:32-50, internal/oauth/service.go:122-126

Token Security

  • JWT tokens signed with HS256 algorithm
  • Secret key stored in environment variables
  • Token expiration enforced server-side
  • HMAC signature prevents token tampering

Session Management

  • Session cookies for OAuth state
  • Cleanup of stale session data
  • Session secrets from environment configuration
Ensure JWT_SECRET environment variable is set to a strong, random value in production.

Build docs developers (and LLMs) love