Authentication
JWT authentication flow — login, token refresh, and logout
Authentication
The API uses JWT (JSON Web Token) authentication with a two-token system:
- Access Token — Short-lived (15 minutes), used for API requests
- Refresh Token — Long-lived (7 days), used to obtain new access tokens
Token Lifecycle
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Login │────▶│ Access Token │────▶│ API Request │
│ │ │ (15 min) │ │ │
└──────────────┘ └──────┬───────┘ └──────────────┘
│ │
│ Token Expired?
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│Refresh Token │────▶│ New Access │
│ (7 days) │ │ Token │
└──────────────┘ └──────────────┘Login
Obtain access and refresh tokens by providing your credentials.
mutation {
login(username: "your_username", password: "your_password") {
accessToken
refreshToken
expiresIn
user {
id
username
name
email
}
}
}Response:
{
"data": {
"login": {
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"expiresIn": 900,
"user": {
"id": 42,
"username": "api_user",
"name": "API User",
"email": "api@school.ac.th"
}
}
}
}| Field | Type | Description |
|---|---|---|
accessToken | String | JWT token for authenticating requests |
refreshToken | String | Token for obtaining new access tokens |
expiresIn | Int | Access token lifetime in seconds (900 = 15 min) |
user | AuthUser | Authenticated user information |
Using the Access Token
Include the access token in the Authorization header of every request:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...The JWT payload contains:
{
"sub": "42",
"username": "api_user",
"email": "api@school.ac.th",
"schoolId": 123,
"iss": "ns-data",
"iat": 1700000000,
"exp": 1700000900
}Refresh Token
When the access token expires, use the refresh token to get a new one without re-authenticating:
mutation {
refreshToken(refreshToken: "a1b2c3d4-e5f6-7890-abcd-ef1234567890") {
accessToken
expiresIn
}
}Response:
{
"data": {
"refreshToken": {
"accessToken": "eyJhbGciOiJIUzI1NiIs...(new token)",
"expiresIn": 900
}
}
}Note: The refresh token itself is not rotated — you keep using the same refresh token until it expires (7 days) or you logout.
Logout
Invalidate a specific refresh token:
mutation {
logout(refreshToken: "a1b2c3d4-e5f6-7890-abcd-ef1234567890")
}Logout All Sessions
Invalidate all refresh tokens for your account (requires authentication):
mutation {
logoutAll
}This removes all active sessions across all devices.
Error Responses
| Error Code | Description |
|---|---|
UNAUTHENTICATED | Invalid or missing access token |
FORBIDDEN | User not assigned to a school |
Invalid credentials | Wrong username or password |
Invalid or expired refresh token | Refresh token is invalid or has expired |