Guides
Authentication
For practice only
These flows are deliberately simple and use publicly documented demo accounts. Tokens are signed demo JWTs that only work with Mock APIs. Never use this API, these credentials, or these patterns to secure a real application, and never send real passwords to it.
Demo accounts
| Role | Username | Password | Use it to |
|---|---|---|---|
| admin | emilyc | emilycpass | Access every demo route, including /auth/admin |
| user | michaelb | michaelbpass | See a 403 Forbidden on /auth/admin |
Every seeded user can log in with the password <username>pass. You can log in with username or email.
The token flow
POST /auth/loginwith credentials. You receive anaccessToken(default 30 minutes; setexpiresInMinsbetween 1 and 1440) and arefreshToken(7 days).- Send the access token on protected requests:
Authorization: Bearer <accessToken>. - When it expires you get
401 TOKEN_EXPIRED. CallPOST /auth/refreshwith the refresh token to get a new pair.
Practice expiry handling
Log in with "expiresInMins": 1 to get a token that expires after a minute, then exercise your refresh logic.
Registration
POST /auth/register validates the new account (including username and email conflicts with seeded users) and returns tokens for a simulated user. The account is not stored, but its access token works with /auth/me until it expires, so a sign-up form can complete its full flow.
Authentication errors
Failures use the standard error format. 401 responses include a WWW-Authenticate: Bearer header.
| Status | Code | When |
|---|---|---|
| 401 | MISSING_TOKEN | No Authorization header was sent. |
| 401 | INVALID_AUTH_HEADER | The header is not in the form "Bearer <token>". |
| 401 | INVALID_TOKEN | The token is malformed, tampered with, signed by someone else, or the wrong type (e.g. a refresh token sent as an access token). |
| 401 | TOKEN_EXPIRED | The token was valid but has expired. Refresh it or log in again. |
| 401 | INVALID_CREDENTIALS | Wrong username/email or password on login. |
| 403 | FORBIDDEN | The token is valid but the user lacks the required role. |
Where to keep tokens in your app
For learning purposes, keeping the access token in memory and the refresh token in sessionStorage is fine. Real applications should follow their platform's security guidance (for example HTTP-only cookies set by your own backend, or the platform keychain on mobile).
Log in (demo)
/api/v1/auth/loginExchanges demo credentials for a short-lived demo access token and a refresh token. Use username or email. expiresInMins (1-1440) lets you practice token expiry.
Headers
| Name | In | Type | Description |
|---|---|---|---|
Content-Typerequired | header | string | Must be application/json. |
Request body
Demo credentials.
| Field | Type | Required | Notes |
|---|---|---|---|
username | string | No | min length 1, max length 100 |
email | string (email) | No | |
password | string | Yes | min length 1, max length 128 |
expiresInMins | integer | No | min 1, max 1440 |
Status codes
- 200Tokens and the authenticated user.
- 401Wrong username/email or password (
INVALID_CREDENTIALS). - 422The JSON body failed validation (
VALIDATION_ERROR).
Request
curl -X POST 'https://test.naimulhassan.me/api/v1/auth/login' \
-H 'Content-Type: application/json' \
-d '{
"username": "emilyc",
"password": "emilycpass",
"expiresInMins": 30
}'Example responses
Captured from the real API with the requests shown on this page.
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo-payload.demo-signature",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo-payload.demo-signature",
"tokenType": "Bearer",
"expiresIn": 1800,
"demo": true,
"notice": "Demo token for practice only. Do not use Mock APIs authentication to secure real applications.",
"user": {
"id": 1,
"username": "emilyc",
"email": "emily.carter@example.com",
"firstName": "Emily",
"lastName": "Carter",
"role": "admin",
"image": "https://test.naimulhassan.me/api/v1/images/users/1"
}
}Try it
Register (demo, simulated)
/api/v1/auth/registerValidates a registration request and returns tokens for a simulated new user. The account is not stored, but the returned access token works with /auth/me until it expires.
Headers
| Name | In | Type | Description |
|---|---|---|---|
Content-Typerequired | header | string | Must be application/json. |
Request body
New account details.
| Field | Type | Required | Notes |
|---|---|---|---|
firstName | string | Yes | min length 1, max length 50 |
lastName | string | Yes | min length 1, max length 50 |
username | string | Yes | |
email | string (email) | Yes | |
password | string | Yes | min length 8, max length 72 |
Status codes
- 201Tokens and the simulated user.
- 409Username or email already taken by a seeded user (
CONFLICT). - 422The JSON body failed validation (
VALIDATION_ERROR).
Request
curl -X POST 'https://test.naimulhassan.me/api/v1/auth/register' \
-H 'Content-Type: application/json' \
-d '{
"firstName": "Jordan",
"lastName": "Lee",
"username": "jordanlee",
"email": "jordan.lee@example.com",
"password": "supersecret1"
}'Example responses
Captured from the real API with the requests shown on this page.
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo-payload.demo-signature",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo-payload.demo-signature",
"tokenType": "Bearer",
"expiresIn": 1800,
"demo": true,
"notice": "Demo token for practice only. Do not use Mock APIs authentication to secure real applications.",
"user": {
"id": 101,
"username": "jordanlee",
"email": "jordan.lee@example.com",
"firstName": "Jordan",
"lastName": "Lee",
"role": "user",
"image": null
}
}Try it
Get the current user
/api/v1/auth/meReturns the user identified by the demo access token in the Authorization: Bearer <token> header.
Headers
| Name | In | Type | Description |
|---|---|---|---|
Authorizationrequired | header | string | Bearer <accessToken> from login or register. |
Status codes
- 200The authenticated user.
- 401Missing header (
MISSING_TOKEN), malformed header (INVALID_AUTH_HEADER), invalid token (INVALID_TOKEN), or expired token (TOKEN_EXPIRED).
Request
curl 'https://test.naimulhassan.me/api/v1/auth/me' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN'Example responses
Captured from the real API with the requests shown on this page.
{
"id": 1,
"username": "emilyc",
"email": "emily.carter@example.com",
"firstName": "Emily",
"lastName": "Carter",
"role": "admin",
"image": "https://test.naimulhassan.me/api/v1/images/users/1"
}Try it
{{accessToken}} / {{refreshToken}} are replaced with a fresh demo token when you send.
Refresh tokens
/api/v1/auth/refreshExchanges a valid refresh token for a new access token and refresh token.
Headers
| Name | In | Type | Description |
|---|---|---|---|
Content-Typerequired | header | string | Must be application/json. |
Request body
The refresh token from login.
| Field | Type | Required | Notes |
|---|---|---|---|
refreshToken | string | Yes | min length 1, max length 4096 |
expiresInMins | integer | No | min 1, max 1440 |
Status codes
- 200New tokens and the user.
- 401Invalid or expired refresh token (
INVALID_TOKEN/TOKEN_EXPIRED). - 422The JSON body failed validation (
VALIDATION_ERROR).
Request
curl -X POST 'https://test.naimulhassan.me/api/v1/auth/refresh' \
-H 'Content-Type: application/json' \
-d '{
"refreshToken": "YOUR_REFRESH_TOKEN",
"expiresInMins": 30
}'Example responses
Captured from the real API with the requests shown on this page.
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo-payload.demo-signature",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo-payload.demo-signature",
"tokenType": "Bearer",
"expiresIn": 1800,
"demo": true,
"notice": "Demo token for practice only. Do not use Mock APIs authentication to secure real applications.",
"user": {
"id": 1,
"username": "emilyc",
"email": "emily.carter@example.com",
"firstName": "Emily",
"lastName": "Carter",
"role": "admin",
"image": "https://test.naimulhassan.me/api/v1/images/users/1"
}
}Try it
{{accessToken}} / {{refreshToken}} are replaced with a fresh demo token when you send.
Admin-only route
/api/v1/auth/adminPractice role-based authorization. Returns 200 for users with the admin role and 403 for everyone else. Log in as michaelb to see a 403.
Headers
| Name | In | Type | Description |
|---|---|---|---|
Authorizationrequired | header | string | Bearer <accessToken>. |
Status codes
- 200Access granted.
- 401Missing or invalid token.
- 403Authenticated, but not an admin (
FORBIDDEN).
Request
curl 'https://test.naimulhassan.me/api/v1/auth/admin' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN'Example responses
Captured from the real API with the requests shown on this page.
{
"message": "Welcome, Emily! You have access to this admin-only demo route.",
"user": {
"id": 1,
"username": "emilyc",
"email": "emily.carter@example.com",
"firstName": "Emily",
"lastName": "Carter",
"role": "admin",
"image": "https://test.naimulhassan.me/api/v1/images/users/1"
}
}Try it
{{accessToken}} / {{refreshToken}} are replaced with a fresh demo token when you send.