Dev #15

Merged
DeepnaPooja merged 4 commits from dev into production 2026-08-25 22:54:09 +05:30
Showing only changes of commit 08ad17f15b - Show all commits
+102
View File
@@ -0,0 +1,102 @@
# Authentication — Own-User Auth via External Identity Service (AuthHex)
**Status**: Done
**Depends On**: — (cross-cutting infrastructure, not a numbered feature step)
---
## Goal
Own-user (staff/API) authentication is delegated to an external identity service ("AuthHex"),
which owns credentials and signs RS256 JWTs. This app validates those tokens and maps them onto
its own `User`/`Role` tables so the existing permission-policy authorization stays unchanged.
---
## Background / Context
Previously this app verified passwords and minted its own HMAC-signed JWT locally. That's been
replaced — AuthHex now owns credentials and signing; this app only holds AuthHex's **public** key
to validate tokens, and never sees a plaintext password for this flow.
Authorization is untouched: permission policies, role levels, scope checks, and the seeded role
set all still work exactly as before, because every validated token is mapped back onto a local
`User`/`Role` row before any authorization check runs.
---
## Configuration Changes
```jsonc
"Jwt": {
"PublicKey": "<RSAKeyValue>...</RSAKeyValue>",
"Audience": "AuthHexClient",
"Issuer": "AuthHex"
},
"AuthHex": { "BaseUrl": "http://localhost:6102" }
```
`Jwt:Key` (old symmetric secret) is removed. `Jwt:PublicKey` is AuthHex's RSA public key in XML
format (not PEM).
---
## API Endpoints
| Method | Route | Notes |
|---|---|---|
| POST | /api/auth/login | Proxies to AuthHex `loginUser` |
| POST | /api/auth/register | Proxies to AuthHex `registerUser` |
| GET | /api/auth/me | `[Authorize]`, proxies to AuthHex `getUserDetails` |
| POST | /api/auth/logout | `[Authorize]`, proxies to AuthHex `LogoutUser` |
All four just forward to `POST {AuthHex:BaseUrl}/api/user` and pass AuthHex's response back
as-is. No cookie — token returned in the response body, sent back as `Authorization: Bearer`.
---
## Business Rules
1. No local password check or token issuance — both delegated to AuthHex.
2. `AddJwtBearer` validates issuer/audience/signature/lifetime against AuthHex's public key.
3. `OnTokenValidated` maps the token's `sub` claim to a local `User` (`IUserRepository`); fails
the token if no matching active user exists.
4. On success, `username`/`role_id`/`role_level` claims are attached from the **local** `User`/
`Role` row — authorization checks downstream are unaffected by anything AuthHex's own token
claims contain.
5. Only one validation mechanism runs (`AddJwtBearer`) — two ported alternatives exist but are not
registered (see Implementation Notes).
6. No refresh tokens — once the AuthHex-issued token expires, the client must log in again.
---
## Permissions to Add to Seed
None — this only changes authentication. Permission policies and role seed data are untouched.
---
## Open Questions
- Add a refresh-token flow if AuthHex doesn't offer one and re-login UX proves disruptive.
- Keep or delete the ported `AuthMiddleware`/`JwtMiddleware` if never actually needed.
- No retry/circuit-breaker if AuthHex is unreachable.
---
## Implementation Notes
```
Features/Auth/ — AuthController, AuthService, AuthDTOs (thin AuthHex proxies)
Infra/Authorization/
AuthHex/ — IAuthHexClient, AuthHexClient, AuthHexResponse
Jwt/RsaXmlKeyReader.cs — portable XML→RSA key parser (RSA.FromXmlString is Windows-only)
Middleware/ — AuthMiddleware, JwtMiddleware, JwtOptions, ApiResponse
(ported from OSMCore for reference — NOT registered)
Program.cs — AddHttpClient<IAuthHexClient>, AddJwtBearer + OnTokenValidated
(maps token → local User/Role → role_id/role_level claims)
```
**Gotcha:** don't run more than one of `AddJwtBearer` / `AuthMiddleware` /
`JwtMiddleware.CustomMiddlewareAttribute` at once — each re-validates the same token
independently.