Authentication and user accounts API

1. Login

WeChat Mini Program login:

POST /api/v1/auth/login/wechat

Body:

{
  "code": "temporary login credential returned by Mini Program wx.login()",
  "totp_code": "123456"
}

Notes:

  • The backend exchanges code with the WeChat server for an openid, then finds the user bound to that openid.

  • Mini Programs do not support cookies. Tokens are returned directly in the response body, and the Mini Program must store them itself.

  • totp_code is required when the account has TOTP enabled.

Email, student ID, or staff ID plus password login:

POST /api/v1/auth/login/email

Body:

{
  "email": "teacher@school.edu",
  "password": "your_password",
  "totp_code": "123456"
}

Notes:

  • email accepts either an email address or user_code.

  • totp_code is required when the account has TOTP enabled.

  • Accounts with TOTP enabled must also include totp_code in the request body when using WeChat login.

1.1 Two-factor authentication (TOTP)

Set up a time-based one-time password for the account:

POST /api/v1/auth/totp/setup

Example response:

{
  "code": 0,
  "message": "success",
  "data": {
    "secret": "BASE32SECRET",
    "provisioning_uri": "otpauth://totp/Classroom%20Manager:tester%40school.edu?..."
  }
}

After scanning the QR code, submit the verification code to enable TOTP:

POST /api/v1/auth/totp/enable

Body:

{
  "totp_code": "123456"
}

1.2 Passwordless login (WebAuthn)

The system supports WebAuthn authentication with security keys and platform devices. The flow has two steps: key registration and login. All endpoints follow the unified success/error response structure.

Register a security key (authenticated)

  1. Request registration options. Pass optional device_name to label the device.

POST /api/v1/auth/webauthn/options/register

The response contains the publicKey options required by browser navigator.credentials.create.

  1. Submit the credential generated by the browser.

POST /api/v1/auth/webauthn/register

Example body:

{
  "credential": { ... },
  "device_name": "MacBook Touch ID"
}

Login with a security key (anonymous)

  1. Request login options.

POST /api/v1/auth/webauthn/options/login

Body:

{ "identifier": "teacher@school.edu" }
  1. Submit the authentication result to obtain a JWT.

POST /api/v1/auth/webauthn/login

Body:

{ "credential": { ... } }

Disable TOTP authentication:

POST /api/v1/auth/totp/disable

Body:

{
  "totp_code": "123456"
}

If TOTP is currently enabled, the verification code is required to confirm the change.

2. Invite a foreign teacher to register (admin)

POST /api/v1/users/invite-foreign

Body:

{
  "email": "teacher@school.edu",
  "full_name": "John Smith"
}

3. Email registration (foreign teacher)

POST /api/v1/auth/register/email

Body:

{
  "email": "teacher@school.edu",
  "password": "12345678",
  "full_name": "John Smith"
}

Notes:

  • The user is logged in automatically after successful registration.

  • The default role for the new user is foreign_teacher.

4. Get current user information

GET /api/v1/auth/me

5. User list (admin)

GET /api/v1/users

Query:

  • role (optional)

  • status (optional)

  • search (optional; matches name, student ID, or staff ID)

  • page, page_size (also supports size)

6. Create user (superadmin / secretary)

POST /api/v1/users

Body:

{
  "user_code": "2024123456",
  "username": "johnsmith",
  "full_name": "John Smith",
  "email": "johnsmith@school.edu",
  "roles": ["student"],
  "password": "optional_password"
}

Notes:

  • If no password is provided, the default password is defaultPass123.

7. Update user information (superadmin / secretary)

PUT /api/v1/users/{id}

8. Change role (superadmin)

PUT /api/v1/users/{id}/role

Body:

{ "role": "assistant" }

9. Disable or enable account (superadmin / secretary)

PUT /api/v1/users/{id}/status

Body:

{ "status": "active" }

10. Import users from Excel (superadmin / secretary)

POST /api/v1/users/import
Content-Type: multipart/form-data

Fields:

  • file: Excel file.

Header conventions:

  • Required: student ID, staff ID, user_code, or combined student/staff ID column; and name or full_name.

  • Optional: username or username, email or email, role or role.

  • If username is empty, the backend falls back to user_code.

  • If role is empty, the backend defaults to student.

  • The template no longer contains a password column. Even if an Excel file contains that column, the backend does not import it as the login password.

Import strategy:

  • Backend user_code is used as the unique key. Existing users are skipped and not overwritten.

  • Newly imported users are created with active status, and Django set_unusable_password() is called to set an unusable password.

  • To enable password login, an administrator must set a password separately through the user edit API after import.

11. Refresh token

POST /api/v1/auth/token/refresh

Body for Mini Program clients:

{
  "refresh": "refresh_token_here"
}

Notes:

  • Web: refresh_token is read automatically from the HttpOnly cookie.

  • Mini Program: provide refresh or refresh_token in the request body.

12. Logout

POST /api/v1/auth/logout

Notes:

  • Clears authentication cookies for web clients.

13. Bind Weixin/WeChat

Bind the current logged-in user to a WeChat openid. After binding, the user can log in with one tap through WeChat.

POST /api/v1/auth/wechat/bind

Body:

{
  "code": "temporary login credential returned by Mini Program wx.login()"
}

Permission: login required.

14. Unbind Weixin/WeChat

Remove the binding between the current user and WeChat.

POST /api/v1/auth/wechat/unbind

Permission: login required.

15. Get SM2 public key

Used by the frontend to encrypt sensitive data, such as passwords in transit.

GET /api/v1/accounts/sm2/public-key

Permission: no login required.

Response:

{
  "code": 0,
  "message": "success",
  "data": {
    "public_key": "SM2 public key string",
    "fingerprint": "public key fingerprint"
  }
}