Authentication
The API uses JWT (JSON Web Tokens) with HS256 signing for stateless authentication, combined with a refresh token system for long-lived sessions.
Login Flow
Client API
│ │
├─ POST /api/auth/org/login ───►│
│ { email, password } │ Validate credentials
│ │ Check account status
│ │ Check login rate limit
│◄── { accessToken, │
│ refreshToken } ─────────│
│ │
├─ GET /api/orgs/{id}/events ──►│
│ Authorization: Bearer ... │ Validate JWT
│ │ Extract org + role claims
│◄── { events } ────────────────│
Endpoints
Login
POST /api/auth/org/login
Content-Type: application/json
{
"email": "[email protected]",
"password": "your-password"
}
{
"accessToken": "eyJhbGci...",
"refreshToken": "eyJhbGci...",
"tokenType": "Bearer",
"expiresIn": 3600
}
System Login (Platform Admins)
POST /api/auth/system/login
Content-Type: application/json
{
"email": "[email protected]",
"password": "admin-password"
}
Refresh Token
POST /api/auth/tokens/refresh
Content-Type: application/json
{
"refreshToken": "eyJhbGci..."
}
Revoke Token
POST /api/auth/tokens/revoke
Authorization: Bearer <accessToken>
Password Reset
# 1. Request reset code (sent via email)
POST /api/auth/password-reset/request
{ "email": "[email protected]" }
# 2. Reset with code
POST /api/auth/password-reset/verify
{ "email": "[email protected]", "code": "123456", "newPassword": "..." }
# 3. Resend code
POST /api/auth/password-reset/resend
{ "email": "[email protected]" }
JWT Token Structure
Access Token Claims
{
"sub": "user-uuid",
"email": "[email protected]",
"username": "johndoe",
"userType": "ORGANIZATION",
"organizationId": "org-uuid",
"organizationRole": "ADMIN",
"iat": 1712500000,
"exp": 1712503600,
"iss": "associationapp"
}
For system users:
{
"sub": "user-uuid",
"userType": "SYSTEM",
"systemRole": "SUPER_ADMIN",
...
}
Token Lifetimes
| Token | Lifetime |
|---|---|
| Access Token | 1 hour |
| Refresh Token | 30 days |
| Email Verification | 7 days |
| Password Reset Code | Configurable |
Using the Token
Include the access token in every authenticated request:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Role Hierarchy
System Roles (Platform-wide)
These apply to platform administrators who manage the system itself.
| Role | Level | Access |
|---|---|---|
SUPER_ADMIN | 100 | Full platform access |
PLATFORM_ADMIN | 80 | Manage multiple organisations |
SUPPORT_ADMIN | 60 | Customer support |
READ_ONLY_ADMIN | 40 | View-only access |
Organisation Roles
These apply to users within a specific organisation.
| Role | Access |
|---|---|
OWNER | Full org access, including delete |
ADMIN | Manage members, events, content |
MANAGER | Create/edit events, manage registrations |
MEMBER | View content, register for events |
GUEST | Limited read-only access |
Authority System
Fine-grained permissions follow the format CATEGORY:RESOURCE:ACTION.
Examples
SYSTEM:USER:CREATE
SYSTEM:USER:DELETE
ORG:EVENT:CREATE
ORG:EVENT:PUBLISH
ORG:MEMBER:INVITE
ORG:BILLING:VIEW
ORG:NEWS:PUBLISH
ORG:DOCUMENT:DELETE
Authorities are assigned to roles and checked via Spring Security annotations.
Account Status
User Account States
| Status | Description |
|---|---|
PENDING_VERIFICATION | Email not yet verified |
ACTIVE | Normal access |
SUSPENDED | Temporarily banned |
DEACTIVATED | User-initiated (self-disabled) |
BANNED | Permanently banned |
Organisation Membership States
| Status | Description |
|---|---|
PENDING | Invitation sent, awaiting acceptance |
ACTIVE | Full member access |
SUSPENDED | Cannot access organisation |
INACTIVE | Left or removed |
REJECTED | Join request was rejected |
Rate Limiting
Login attempts are rate-limited to prevent brute-force attacks.
| Setting | Default |
|---|---|
| Max failed attempts | 5 |
| Lockout duration | 15 minutes |
After the lockout period expires, the counter resets automatically.
Multi-Factor Authentication (MFA)
The API includes TOTP-based MFA support with backup codes. When MFA is enabled for an account:
- User logs in with email + password
- API returns a
mfa_requiredchallenge - Client submits the TOTP code
- API issues access + refresh tokens
Multi-Tenant Security
- The
organizationIdclaim in the JWT automatically scopes all queries - Users can only access data belonging to their organisation
- System admins (
SYSTEMuser type) bypass organisation scoping - All entities use soft deletes (
deleted_attimestamp) for data isolation
Token Rotation Strategies
Configurable via system settings:
| Strategy | Behaviour |
|---|---|
CREATE_NEW | New refresh token on every use |
UPDATE_EXISTING | Extend existing token expiry |
LIMIT_PER_DEVICE | One active token per device |
LIMIT_TOTAL | Cap on total active tokens per user |