# Auth Router: Login, Token Refresh, and User Management API

# Auth Router: Login, Token Refresh, and User Management API

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [src/modules/auth/casdoor-api-client.ts](src/modules/auth/casdoor-api-client.ts)
- [src/modules/auth/router.ts](src/modules/auth/router.ts)
- [src/modules/auth/user-profiles-dal.ts](src/modules/auth/user-profiles-dal.ts)
- [src/modules/auth/user_profile_entity.ts](src/modules/auth/user_profile_entity.ts)

</details>



The Auth Router provides a centralized interface for authentication proxying and user profile management. It bridges the gap between the external Identity Provider (Casdoor) and the internal application state, implementing Just-In-Time (JIT) provisioning to ensure that every authenticated identity has a corresponding internal `uuid` for audit and relational purposes.

### Implementation Overview

The authentication system is designed to be IDP-agnostic within the core business logic while using Casdoor for credential management. The `authRouter` [src/modules/auth/router.ts:24-42]() initializes specialized services:
- **`CasdoorApiClient`**: Handles administrative operations (CRUD) against the Casdoor REST API [src/modules/auth/casdoor-api-client.ts:42-53]().
- **`UserProfilesDal`**: Manages the `user_profiles` table, which mirrors IDP identities [src/modules/auth/user-profiles-dal.ts:67-74]().
- **`AuditService`**: Records changes to user profiles and administrative actions [src/modules/auth/router.ts:29-34]().

### Login Data Flow and Proxying

The `/api/v1/auth/login` endpoint [src/modules/auth/router.ts:68-70]() acts as a secure proxy to Casdoor's OAuth2 token endpoint. This pattern ensures that `client_secret` and `client_id` never leave the backend environment.

#### Login Sequence
1. **Validation**: The request body is validated against `LoginBodySchema` (username/password) [src/modules/auth/router.ts:19-22]().
2. **Config Resolution**: Auth settings are loaded from the database via `loadAuthConfigFromDb` [src/modules/auth/router.ts:99-103]().
3. **Outbound Proxy**: The backend performs a `POST` to Casdoor's `/api/login/oauth/access_token` using `grant_type: password` [src/modules/auth/router.ts:113-141]().
4. **Error Mapping**: Specific Casdoor errors (e.g., "too many failed attempts") are parsed and mapped to user-friendly messages [src/modules/auth/router.ts:160-174]().

#### Login Proxy Logic
```mermaid
sequenceDiagram
    participant Client as "Web Client"
    participant API as "authRouter (Backend)"
    participant DB as "PostgreSQL (auth_config)"
    participant IDP as "Casdoor"

    Client->>API: POST /api/v1/auth/login (username, password)
    API->>DB: loadAuthConfigFromDb()
    DB-->>API: clientId, clientSecret, endpoint
    API->>IDP: POST /api/login/oauth/access_token (grant_type=password)
    IDP-->>API: Access Token + ID Token
    API-->>Client: 200 OK (JWT Payload)
```
**Sources:** [src/modules/auth/router.ts:68-180](), [src/modules/auth/config-repo.ts:1-20]()

---

### Token Refresh and JIT Provisioning

The `/api/v1/auth/refresh` endpoint [src/modules/auth/router.ts:203-205]() handles token renewal and ensures the internal `user_profiles` record is synchronized with the IDP.

#### Just-In-Time (JIT) Logic
When a token is refreshed or a user logs in, the system checks if the `idp_code` (the IDP's `sub` claim) exists in the `user_profiles` table [src/modules/auth/user_profile_entity.ts:12-17]().
- **If missing**: A new record is inserted with a fresh internal `uuid` [src/modules/auth/user_profile_entity.ts:15]().
- **If present**: The `last_synced_at` field is updated [src/modules/auth/user_profile_entity.ts:75-77]().

This mechanism prevents vendor-specific IDs (like Casdoor's `org/user` format) from leaking into business tables or audit logs, as all internal foreign keys reference the generated `uuid` [src/modules/auth/user_profile_entity.ts:8-10]().

**Sources:** [src/modules/auth/router.ts:203-270](), [src/modules/auth/user_profile_entity.ts:1-20]()

---

### User Management and Administrative API

The router provides a full suite of CRUD operations for user management, protected by RBAC permissions [src/modules/auth/router.ts:316-320]().

| Endpoint | Permission | Description |
| :--- | :--- | :--- |
| `GET /api/v1/auth/users` | `Permission.USER_LIST` | Paginated list with filtering/search [src/modules/auth/router.ts:316](). |
| `GET /api/v1/auth/users/:uuid` | `Permission.USER_READ` | Detailed profile view with audit metadata [src/modules/auth/router.ts:348](). |
| `PATCH /api/v1/auth/users/:uuid` | `Permission.USER_UPDATE` | Update roles, status, or profile info [src/modules/auth/router.ts:384](). |
| `DELETE /api/v1/auth/users/:uuid` | `Permission.USER_DELETE` | Soft-delete a user profile [src/modules/auth/router.ts:466](). |
| `POST /api/v1/auth/users/:uuid/restore` | `Permission.USER_RESTORE` | Restore a soft-deleted user [src/modules/auth/router.ts:494](). |

#### Administrative Data Flow
```mermaid
graph TD
    subgraph "Auth Router"
        R[router.patch '/users/:uuid']
    end

    subgraph "Data Access Layer"
        DAL[UserProfilesDal.updateProfile]
        Repo[Repository.update]
    end

    subgraph "External Sync"
        CDC[CasdoorApiClient.updateUser]
    end

    R --> DAL
    DAL --> Repo
    DAL -.-> CDC
    Repo --> DB[("user_profiles table")]
```
**Sources:** [src/modules/auth/router.ts:384-464](), [src/modules/auth/user-profiles-dal.ts:97-102](), [src/modules/auth/casdoor-api-client.ts:105-159]()

---

### Profile Self-Service and Avatars

Users can manage their own profiles via the `/api/v1/auth/me` endpoint [src/modules/auth/router.ts:275-277]().

#### Avatar Generation
If a user does not have an avatar URL, the system generates initials and a background color based on their `display_name` [src/modules/auth/router.ts:285-300]().
- **`avatar_initials`**: Derived from the first letters of the display name.
- **`avatar_color`**: Deterministically generated from a hash of the user's ID or name to ensure consistency across sessions.

#### Profile Update Logic
When a user updates their profile (e.g., changing a display name), the `UserProfilesDal` performs a dual-write:
1. It updates the local `user_profiles` table using the `Repository` [src/modules/auth/user-profiles-dal.ts:101]().
2. It attempts to sync the change back to Casdoor via the `CasdoorApiClient` if credentials are available [src/modules/auth/router.ts:436-456]().

**Sources:** [src/modules/auth/router.ts:275-314](), [src/modules/auth/user-profiles-dal.ts:97-102](), [src/modules/auth/casdoor-api-client.ts:105-131]()

---

### Soft-Delete and Audit Trail

User profiles implement the `IAuditableEntity` interface [src/modules/auth/user_profile_entity.ts:39]().
- **Soft-Delete**: Uses the `@DeletableField` decorator on `deleted_at` and `deleted_by` [src/modules/auth/user_profile_entity.ts:109-113]().
- **Audit Logging**: Every change is captured by the `AuditService`. The `UserProfilesDal` includes a specialized `getUserProfileAudit` method that enriches the audit delta with display names for better readability [src/modules/auth/user-profiles-dal.ts:183-205]().

**Sources:** [src/modules/auth/user_profile_entity.ts:94-114](), [src/modules/auth/user-profiles-dal.ts:211-260]()

---
