Repository navigation
Identity, JWT auth and tenant scoping - #1
Merged
Merged
Conversation
- Employee domain entity with deactivate/reactivate/anonymise rules - ApplicationUser on Identity with GUID keys, linked to tenant - Partial unique index: an email belongs to at most one active account - Unit tests for employee rules; integration tests for email uniqueness
- IIdentityService in Application hides ASP.NET Core Identity types - Duplicate active email detected from the database unique index (race-safe) - Expected failures returned as results; integration tests for each outcome
- POST /api/v1/auth/register creates tenant, owner login and Administrator employee - Single transaction via IUnitOfWork; failure at any step rolls back - 409 for email already active elsewhere, 400 for validation/password policy
Tenants are now created only via POST /api/v1/auth/register together with their owner. Tenant tests seed data through the DbContext instead.
- ITokenService issues HS256 access tokens with sub, employee_id, tenant_id, role and jti - JwtOptions validated at startup; signing key from user-secrets/env vars, never in appsettings - TimeProvider injected so expiry is unit-testable
- POST /api/v1/auth/login returns a JWT for the single active account with that email - Lockout after 5 failures; checked before the password - Same 401 for unknown email, wrong password, inactive or locked account; 403 for suspended distributor
- Validates issuer, audience, signature, lifetime; HS256 only; 30s clock skew - Claim names kept as issued (MapInboundClaims = false) - GET /api/v1/me proves end to end; tests for missing, tampered, foreign-key, expired and wrong-audience tokens
AddApplication, AddInfrastructure, AddApiControllers and AddJwtAuthentication keep each layer's wiring next to its code. No behaviour change.
ICurrentTenant reads tenant_id only from the request's signed JWT; returns null for anonymous requests (login, register).
- Employee queries are filtered by the current tenant from the JWT; no tenant sees nothing - Login lookup explicitly ignores the filter (no tenant before login) - Isolation tests (A cannot see B) and a model test requiring a filter on every TenantId entity
- GET/PUT /api/v1/tenant read the tenant from the JWT; no id in the route - Update restricted to Administrator; IsActive no longer client-settable - Removed list-all and deactivate endpoints (platform-level, not per distributor)
- Fallback authorization policy requires an authenticated user on every endpoint - Health check and OpenAPI explicitly opt out with AllowAnonymous - Test lists the exact set of public endpoints so new ones are reviewed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.