Skip to content

🔐 Fake Auth API (JWT login)

Practise login screens, token storage and authenticated requests with demo accounts.

Every app needs a login screen, and testing it usually means waiting for a backend. The Fake Auth API answers like a real one: send a username and password, receive an access token and a refresh token (signed JWTs), then send Authorization: Bearer <token> to get the current user.

Wrong passwords return 401, expired or edited tokens are rejected, and you can choose a short lifetime to test your refresh logic. Demo only: the signing key is public, so never use these tokens to protect real data.

Base URL https://toolorca.com/api/v1 No key · CORS open · JSON · conventions and limits

Endpoints

POST /api/v1/auth/login #

Log in with a demo user. Returns tokens and the user.

Parameter In Type Description
username required body string A demo username (or email), e.g. sokha.chan.
password required body string Always demo1234.
expiresInMins body integer Access token lifetime, 1–1440 minutes (default 60).
curl -X POST 'https://toolorca.com/api/v1/auth/login' \
  -H 'Content-Type: application/json' \
  -d '{"username":"sokha.chan","password":"demo1234","expiresInMins":60}'
POST /auth/login
Example response
{
  "tokenType": "Bearer",
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoic29raGEuY2hhbiIsInJvbGUiOiJhZG1pbiIsInR5cGUiOiJhY2Nlc3MiLCJpYXQiOjE3OTQ2MzMzMjUsImV4cCI6MTc5NDYzNjkyNSwiaXNzIjoidG9vbG9yY2EtZGVtbyJ9.ttto7BIBx6WYDPWmgQvwy6LiIYlsLdE_MaHcjAgEquQ",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInR5cGUiOiJyZWZyZXNoIiwiaWF0IjoxNzk0NjMzMzI1LCJleHAiOjE3OTUyMzgxMjUsImlzcyI6InRvb2xvcmNhLWRlbW8ifQ.ngcT7bCNwPLwfyEDksZs_P_blxgXsPhALKTQWiy2Tfs",
  "expiresIn": 3600,
  "user": {
    "id": 1,
    "firstName": "Sokha",
    "lastName": "Chan",
    "fullName": "Chan Sokha",
    "firstNameKm": "សុខា",
    "lastNameKm": "ចាន់",
    "fullNameKm": "ចាន់ សុខា",
    "username": "sokha.chan",
    "email": "sokha.chan@example.com",
    "phone": "+855 17 915 876",
    "gender": "female",
    "birthDate": "1984-12-24",
    "age": 41,
    "role": "admin",
    "avatar": "https://toolorca.com/api/v1/images/placeholder/200x200.png?text=SC&bg=0f6fde&fg=ffffff",
    "address": {
      "street": "No. 13, Street 2004",
      "city": "Phnom Penh",
      "cityKm": "ភ្នំពេញ",
      "postalCode": "12072",
      "country": "Cambodia",
      "countryCode": "KH",
      "coordinates": {
        "lat": 11.5344,
        "lng": 104.9561
      }
    },
    "company": {
      "name": "Sabay Learning Center",
      "department": "Marketing",
      "title": "Mobile Developer"
    },
    "language": "km",
    "createdAt": "2024-02-22T00:00:00Z"
  }
}

GET /api/v1/auth/me #

The user that owns the access token.

Returns 401 with code missing_token, invalid_token or token_expired when the token is missing, edited or too old. Try it logs in as sokha.chan first.

Parameter In Type Description
Authorization required header string Bearer <accessToken>
curl 'https://toolorca.com/api/v1/auth/me' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
GET /auth/me
Example response
{
  "id": 1,
  "firstName": "Sokha",
  "lastName": "Chan",
  "fullName": "Chan Sokha",
  "firstNameKm": "សុខា",
  "lastNameKm": "ចាន់",
  "fullNameKm": "ចាន់ សុខា",
  "username": "sokha.chan",
  "email": "sokha.chan@example.com",
  "phone": "+855 17 915 876",
  "gender": "female",
  "birthDate": "1984-12-24",
  "age": 41,
  "role": "admin",
  "avatar": "https://toolorca.com/api/v1/images/placeholder/200x200.png?text=SC&bg=0f6fde&fg=ffffff",
  "address": {
    "street": "No. 13, Street 2004",
    "city": "Phnom Penh",
    "cityKm": "ភ្នំពេញ",
    "postalCode": "12072",
    "country": "Cambodia",
    "countryCode": "KH",
    "coordinates": {
      "lat": 11.5344,
      "lng": 104.9561
    }
  },
  "company": {
    "name": "Sabay Learning Center",
    "department": "Marketing",
    "title": "Mobile Developer"
  },
  "language": "km",
  "createdAt": "2024-02-22T00:00:00Z"
}

POST /api/v1/auth/refresh #

Swap a refresh token (valid 7 days) for a new access token and refresh token.

Parameter In Type Description
refreshToken required body string The refresh token from login.
expiresInMins body integer New access token lifetime (default 60).
curl -X POST 'https://toolorca.com/api/v1/auth/refresh' \
  -H 'Content-Type: application/json' \
  -d '{"refreshToken":"YOUR_REFRESH_TOKEN","expiresInMins":60}'
POST /auth/refresh
Example response
{
  "tokenType": "Bearer",
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoic29raGEuY2hhbiIsInJvbGUiOiJhZG1pbiIsInR5cGUiOiJhY2Nlc3MiLCJpYXQiOjE3OTQ2MzMzMjUsImV4cCI6MTc5NDYzNjkyNSwiaXNzIjoidG9vbG9yY2EtZGVtbyJ9.ttto7BIBx6WYDPWmgQvwy6LiIYlsLdE_MaHcjAgEquQ",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInR5cGUiOiJyZWZyZXNoIiwiaWF0IjoxNzk0NjMzMzI1LCJleHAiOjE3OTUyMzgxMjUsImlzcyI6InRvb2xvcmNhLWRlbW8ifQ.ngcT7bCNwPLwfyEDksZs_P_blxgXsPhALKTQWiy2Tfs",
  "expiresIn": 3600
}

Demo accounts

All 30 fake users can log in with the password demo1234. Good ones to start with: sokha.chan (admin), dara.sok (moderator), sophea.kim (moderator), vannak.heng, emma.wilson and liam.nguyen. The full list is at /users (field username); logging in with the email works too.

A typical login flow

1. POST the form to /auth/login and store accessToken and refreshToken in secure storage (Keychain, EncryptedSharedPreferences or flutter_secure_storage). 2. Send the access token as a Bearer header on every request. 3. When a request returns 401 with token_expired, call /auth/refresh once and retry. 4. If refresh fails too, send the user back to the login screen.

Log in with "expiresInMins": 1 to see the expiry path within a minute.

Frequently asked questions

Are the tokens real JWTs?

Yes, HS256-signed JWTs you can decode on jwt.io. The secret is public, so they are only for testing.

Can I register new users?

POST /users returns a new user object, but it is not saved, so it cannot log in. Use the demo accounts.

Does logout exist?

With JWTs, logging out means deleting the tokens on the device. There is nothing to call on the server.

Why do I get 401 invalid_token?

The header must be exactly Authorization: Bearer <accessToken>. A refresh token or an edited token is rejected.

More free APIs