AccessGuard is a multi-tenant authentication and authorization platform designed to operate like a hosted auth provider (e.g., Clerk/Auth0) with an API-first architecture. It supports user login, role-based access control (RBAC), JWT issuance, public key token verification, event logging, and suspicious activity notifications.
- Tenant Management
- Tenants can register with AccessGuard
- Each tenant receives isolated user/role namespace
- Each tenant has an API key and a public/private key pair for JWT signing/verification
- User Management
- Register user (with metadata: email, phone, etc.)
- Login user (issues JWT)
- Refresh token support (future)
- Logout user (optional token revocation, V2)
- Role Management
- Tenants define roles
- Assign roles to users
- Roles are embedded in JWT claims
- JWT Support
- Signed using RS256
- Claims:
sub
,tenant_id
,roles
,iat
,exp
,jti
- Exposed public keys via JWKS (
/.well-known/jwks.json
) - Token verification occurs on the tenant's server using the public key
- Usage Tracking via Webhook
- Aspect Oriented Annotations used to make calls to usage service
- Logs actions in Elastic Search for further analysis if required
- Login Event Logging + Notification
- On successful login, AccessGuard publishes a Kafka event
- A consumer service:
- Logs the login event in
LoginHistory
Compares login IP to TrustedIP for that userIf new/unseen IP, sends notification (email/SMS/webhook)
- Logs the login event in
Trusted IP ManagementMaintains per-userTrustedIP
listCan auto-enroll IPs post-login or keep manual-only
Method | Endpoint | Description |
---|---|---|
POST | /v1/tenant/register |
Register new tenant (Tenant ) |
GET | /v1/tenant/{id} |
Fetch tenant metadata |
PATCH | /v1/tenant/{id} |
Update tenant (e.g., name) |
DELETE | /v1/tenant/{id} |
Deactivate/delete tenant (soft delete recommended) |
PATCH | /v1/tenant/keys |
Rotate public/private key pair (JWT) |
Method | Endpoint | Description |
---|---|---|
POST | /v1/user/register |
Register user under tenant |
GET | /v1/user/{id} |
Fetch user details |
PATCH | /v1/user/{id} |
Update user metadata (email , phone ) |
DELETE | /v1/user/{id} |
Deactivate user (soft delete) |
POST | /v1/user/login |
Login user, issue JWT |
POST | /v1/user/{id}/assign-role |
Assign one or more roles |
DELETE | /v1/user/{id}/unassign-role |
Remove one or more roles |
Method | Endpoint | Description |
---|---|---|
POST | /v1/role/create |
Define a role |
GET | /v1/role/{id} |
Get role by ID |
GET | /v1/role/list?tenantId=X |
List roles for a tenant |
PATCH | /v1/role/{id} |
Update role metadata |
DELETE | /v1/role/{id} |
Delete a role |
Method | Endpoint | Description |
---|---|---|
GET | /v1/keys/public |
Return current public keys (JWKS) |
GET | /.well-known/jwks.json |
JWKS-compliant discovery endpoint |
Method | Endpoint | Description |
---|---|---|
GET | /v1/trusted-ip/{userId} |
List user's trusted IPs |
POST | /v1/trusted-ip |
Add IP manually |
DELETE | /v1/trusted-ip/{id} |
Remove a trusted IP |
accessguard.login.events
(produced by AuthService)- (Future)
accessguard.alerts.generated
(if alerting is decoupled)
Tenant
tenantID
,name
,apiKeyHash
,publicKey
,privateKey
,createdAt
User
tenantID
,email
,phone
,roles
,passwordHash
,createdAt
,passwordUpdatedAt
Role
id
,tenantId
,name
,description
~~TrustedIP~~
~~id
,userId
,ip
,createdAt
~~
LoginHistory
id
,userId
,ip
,ua
,timestamp
,tenantId
UsageLog
id
,tenantId
,userId
,tokenId
,ip
,ua
,endpoint
,method
,timestamp
Endpoints:
POST /v1/user/register
POST /v1/user/login
POST /v1/user/{id}/assign-role
DELETE /v1/user/{id}/unassign-role
Functions:
- Registers users into
User
- Authenticates credentials (via tenant config)
- Issues JWT (claims include:
sub
,tenant_id
,roles
,iat
,exp
,jti
) - Publishes to Kafka:
accessguard.login.events
- Performs IP enrichment and default
TrustedIP
logic
Endpoints:
POST /v1/tenant/register
GET /v1/tenant/{id}
PATCH /v1/tenant/{id}
DELETE /v1/tenant/{id}
PATCH /v1/tenant/keys
Functions:
- Creates and manages
Tenant
- Assigns API keys and key pairs (JWT signing)
- Controls manual key rotation (
privateKey
,publicKey
) - Performs soft-deletion with cascading policy
Endpoints:
POST /v1/role/create
GET /v1/role/{id}
GET /v1/role/list?tenantId=X
PATCH /v1/role/{id}
DELETE /v1/role/{id}
Functions:
- Manages
Role
data - Allows per-tenant role creation
- Supports assignment metadata (used by AuthService)
Triggered via Kafka only
Reads:
- Kafka Topic:
accessguard.login.events
Functions:
- Checks
TrustedIP
perUser
- Writes to
LoginHistory
(id, ip, ua, tenantId) - Sends notification if IP is suspicious:
- Email (SMTP or 3rd-party)
- SMS (Twilio or similar)
- Webhook (future)
- Failsafe: Retry logic or DLQ (V2)
Endpoints:
POST /v1/usage
GET /v1/usage/{tenantId}
Functions:
- Accepts structured payloads
- Writes to
UsageLog
(tokenId, ip, ua, endpoint, etc.) - Authenticates via
apiKey
(fromTenant
) - Provides tenant-filtered analytics endpoint
Endpoints:
~~GET /v1/trusted-ip/{userId}~~
~~POST /v1/trusted-ip~~
~~DELETE /v1/trusted-ip/{id}~~
Functions:
Reads/writes toTrustedIP
Validates IPs and applies tenant-specific policyOptionally supports auto-enrollment mode
Endpoints:
GET /v1/keys/public
GET /.well-known/jwks.json
Functions:
- Serves JWKS for each tenant’s public key
- Supports dynamic refresh from DB
- Backed by Redis or in-memory cache for perf
Internal-only; routes all external requests
Functions:
- Validates JWT on incoming calls
- Verifies via
KeyService
+ cached JWKS - Adds tenant context for downstream services
- Performs rate limiting (Redis token bucket pattern)
- Logs structured request metadata (for auditing/future observability)
Internal service discovery
Functions:
- Allows service-to-service resolution (Feign clients)
- Supports dynamic scaling
- Zero runtime config for downstream services
Transport for async events
Topics:
accessguard.login.events
- (future)
accessguard.alerts.generated
Functions:
- Guarantees event propagation
- Allows decoupled pipelines (logging, ML, risk engine in V2+)
Component | Description |
---|---|
PostgreSQL | Stores all structured data: Tenant , User , Role , TrustedIP , LoginHistory , UsageLog |
Redis | Session cache, rate limiting, possibly JWKS caching |
ElasticSearch(optional) | Flexible store for extensible metadata fields or logs |
- Spring Boot
- Spring Security
- Spring Cloud
- Kafka
- PostgreSQL
- Redis (phase 2)
- ElasticSearch
- Docker (deployment)
- Refresh token rotation
- Admin UI
- Token revocation lists
- Fine-grained permission system
- Social login (OAuth2)
- SDKs for client usage reporting
- WebAuthn / MFA
- Role hierarchy and permission expansion
- JWTs signed using RS256 to prevent tampering
- Tenant API keys are required for usage/event endpoints
- IP-based anomaly detection for login alerts
- All events logged for auditing purposes
Assumptions
- Tenants handle API request authentication using AccessGuard-issued JWTs
- Tenants are responsible for passing accurate usage data including IP/UA
- Public key rotation will be manual in V1
Actor: A new app/startup/dev signs up to use AccessGuard.
-
POST /v1/tenant/register
→ Registers the tenant, returns
apiKey
,publicKey
,privateKey
. -
Tenant stores these keys securely (probably only the private one server-side).
-
From now on, all AccessGuard requests made by the tenant include the
apiKey
for usage reporting.
Actor: End-user signing up on the tenant's platform (handled via backend call by tenant).
-
Tenant calls
POST /v1/user/register
→ Payload:
email
,phone
, etc., scoped to that tenant.→ AccessGuard stores the user in the tenant’s namespace.
-
AccessGuard returns a user ID (tenant’s system may store it internally).
Actor: End-user attempts to log in to the tenant's platform.
-
Tenant backend verifies credentials.
-
Tenant calls
POST /v1/user/login
→ Payload: tenant ID, user ID or credentials
→ AccessGuard:
- Validates the user
- Issues RS256 JWT with claims
- Publishes
accessguard.login.events
to Kafka - Returns JWT
-
Tenant uses this JWT to secure its own backend APIs.
Actor: Tenant’s backend verifying JWTs on protected endpoints.
- When JWT comes in:
- Tenant's backend reads
tenant_id
claim - Looks up public key for the tenant from:
GET /.well-known/jwks.json
- Verifies RS256 signature
- Decodes claims (
sub
,roles
, etc.)
- Tenant's backend reads
- If valid, tenant proceeds with business logic.
Actor: Kafka consumer reacting to login events.
- AuthService publishes
accessguard.login.events
. - NotificationService:
ChecksTrustedIP
listIf IP is new, stores inLoginHistory
, optionally updatesTrustedIP
- Triggers:
- SMS
- Webhook call (tenant-defined, future)
Two modes:
- ~~Auto mode (default): IP added to
TrustedIP
after successful login.~~ - ~~Manual mode (V2): Tenant exposes their own UI/API to manage IPs. AccessGuard just serves/validates.~~
Actor: Tenant rotates keys and notifies AccessGuard.
- Tenant generates a new key pair.
- Calls
PATCH /v1/tenant/keys
(future V1.1 endpoint) - AccessGuard stores the new pair.
- Tenant starts signing JWTs with the new private key.
- Verification by clients still works as JWKS serves updated public key.
Examples:
- Tenant sends invalid usage data → 400 Bad Request
- JWT expired → Tenant handles 401
- NotificationService fails to notify → Kafka retry or dead-letter (V2)
Actor: AccessGuard services talking to each other (Eureka + Feign)
- AuthService → Kafka → NotificationService
- UsageService persists data to DB
- KeyService serves public keys
- GatewayService handles routing to appropriate downstream service