| Crates.io | eqeqo-api-auth |
| lib.rs | eqeqo-api-auth |
| version | 0.0.1 |
| created_at | 2025-12-29 15:11:14.249353+00 |
| updated_at | 2025-12-29 15:11:14.249353+00 |
| description | Centralized authentication and authorization API for multiple independent services. Manages users, roles, permissions, and service associations. |
| homepage | https://gitlab.com/numanope/eqeqo/bazoj/auth-api |
| repository | https://gitlab.com/numanope/eqeqo/bazoj/auth-api |
| max_upload_size | |
| id | 2010726 |
| size | 326,353 |
Centralized authentication and authorization service for the Eqeqo ecosystem. Issues short-lived tokens, renews them atomically near expiry, and enforces access control with a DB-backed token cache plus periodic cleanup.
Local setup
psql -U postgres -f db/run_all.sql
cp .env.example .env
cargo run
Tests
Integration tests rely on the seeded api_auth DB from db/run_all.sql.
Default server: http://127.0.0.1:7878
cargo test --test api_test
Environment:
AUTH_DATABASE_URL=postgres://USER:PASSWORD@HOST/api_auth
SERVER_PORT=7878
TOKEN_TTL_SECONDS=300
TOKEN_RENEW_THRESHOLD_SECONDS=30
Data reference: see ./db/DB.md (seeded dataset: IDs, users, services, roles, permissions).
token: header (never pass tokens in URLs).auth.tokens_cache; renewal is atomic when near expiry.Example: fetching user data for βJuanβ (id 7) from client servcli1 using an arbitrary token:
curl -X GET "http://127.0.0.1:7878/users/7" \
-H "token: tok_example_123" \
-H "x-client-id: servcli1"
x-client-id is optional metadata; the API currently only enforces the token header.
| Method | Path | Description (minimal example) |
|---|---|---|
| POST | /auth/login |
Issue token for user (global). Example: {"username":"adm1","password":"adm1-hash"} |
| POST | /auth/logout |
Revoke current token. Header: token: <value> |
| GET | /auth/profile |
Validate and optionally renew token. Header: token: <value> |
| POST | /check-token |
Validate token (optional user_id in body to enforce match). Header: token: <value> |
| GET | /users |
List users. Header: token: <value> |
| POST | /users |
Create user. Example body: {"username":"user1","password_hash":"pass","name":"User","person_type":"N","document_type":"DNI","document_number":"123"} + header token. |
| PUT | /users/{id} |
Update user. Example: {"name":"New Name"} + header token. |
| DELETE | /users/{id} |
Delete user and revoke tokens. Header: token. |
| GET | /roles |
List roles. Header: token. |
| POST | /roles |
Create role. Example: {"name":"Editor"} + header token. |
| GET | /roles/{id} |
Get role. Header: token. |
| PUT | /roles/{id} |
Update role. Example: {"name":"New Role"} + header token. |
| DELETE | /roles/{id} |
Delete role. Header: token. |
| GET | /permissions |
List permissions. Header: token. |
| POST | /permissions |
Create permission. Example: {"name":"export"} + header token. |
| PUT | /permissions/{id} |
Update permission. Example: {"name":"export_csv"} + header token. |
| DELETE | /permissions/{id} |
Delete permission. Header: token. |
| POST | /role-permissions |
Assign permission to role. Example: {"role_id":1,"permission_id":2} + header token. |
| DELETE | /role-permissions |
Remove permission from role. Example: {"role_id":1,"permission_id":2} + header token. |
| GET | /roles/{id}/permissions |
List role permissions. Header: token. |
| POST | /services |
Create service. Example: {"name":"Stock","description":"Inventory"} + header token. |
| GET | /services |
List services. Header: token. |
| PUT | /services/{id} |
Update service. Example: {"description":"New desc"} + header token. |
| DELETE | /services/{id} |
Delete service. Header: token. |
| POST | /service-roles |
Assign role to service. Example: {"service_id":1,"role_id":2} + header token. |
| DELETE | /service-roles |
Remove role from service. Example: {"service_id":1,"role_id":2} + header token. |
| GET | /services/{id}/roles |
List roles of a service. Header: token. |
| POST | /person-service-roles |
Assign role to person in service. Example: {"person_id":1,"service_id":1,"role_id":2} + header token. |
| DELETE | /person-service-roles |
Remove role from person in service. Example: {"person_id":1,"service_id":1,"role_id":2} + header token. |
| GET | /people/{person_id}/services/{service_id}/roles |
List roles of person in service. Header: token. |
| GET | /services/{service_id}/roles/{role_id}/people |
List people with role in service. Header: token. |
| GET | /people/{person_id}/services |
List services of a person. Header: token. |
| GET | /people/{person_id}/services/{service_id} |
Get user data plus roles/permissions for that service (may be empty). Header: token. |
| POST | /person-service-permissions |
Grant a permission directly to a person in a service (creates/uses a scoped role). Example: {"person_id":1,"service_id":1,"permission_name":"read"} + header token. |
Generated at login (hash(secret + random + timestamp)). NO JWT nor similar.
Stored centrally in auth.tokens_cache with payload and modified_at; token values are stored hashed (no plaintext).
Tokens are issued per user (global); services query permissions by sending token: + person_id + service_id to /people/{person_id}/services/{service_id}.
All protected requests must include token: header (no query params). /auth/login is the only public route.
Short TTL (2β5 min) with atomic renewal near expiry to avoid contention.
Revocation on logout or user deletion; cleanup job periodically removes expired tokens.
/check-token can optionally validate user to avoid token misuse.
No tokens in URLs.
Minimal logging per request: token, endpoint, timestamp, IP.
Background cleanup job trims expired tokens every ~60 seconds.
sequenceDiagram
autonumber
actor UI as Frontend (UI)
participant BACK as Backend (Stock / Sales / Manufacturing)
participant AUTH as Auth API
%% 1. Login
UI->>AUTH: POST /auth/login { user, pass }
AUTH-->>UI: { token }
%% 2. Request from UI to Back
UI->>BACK: GET /{service_id_string}/{user_id_string}\nheaders: token
%% 3. Cache check + request to Out
alt Valid local cache (<= 1 min)
BACK-->>UI: responds using cached payload
else Expired or missing cache, valid token in Out
BACK->>AUTH: POST /check-token\n{ token, service_id, user_id } (token header, hashed in cache)
AUTH-->>BACK: { valid: true, payload }
BACK-->>UI: responds and saves payload in cache (1 min)
else Expired or missing cache, invalid token in Out
BACK->>AUTH: POST /check-token\n{ token, service_id, user_id } (token header, hashed in cache)
AUTH-->>BACK: { valid: false }
BACK-->>UI: 401 Unauthorized
end
%% 4. Writes always validated
Note over BACK,AUTH: Write operations (POST / PATCH / DELETE)\nalways query Out without using local cache.
%% 5. Logout
UI->>AUTH: POST /auth/logout { token }
AUTH-->>UI: 200 Logged out
MIT Β© Eqeqo