Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save MansourM/3371583006ae0566ff58fc436e603a1c to your computer and use it in GitHub Desktop.
Save MansourM/3371583006ae0566ff58fc436e603a1c to your computer and use it in GitHub Desktop.

πŸ” Central Authentication and Identity Server Proposal

🎯 Goals

1. Unified Authentication (SSO)

  • Enable Single Sign-On (SSO) so users can log in once and access multiple internal apps and dashboards seamlessly.
  • SSO login via OpenID Connect (OIDC), IdP handles authentication only

2. Centralized User Profile (Claims) Management

Establish a single source of truth for user profile data, implemented as structured fields known as claims:

  • A single User Identity Service manages all user data (claims, documents, verification, etc.)

    • Example claims: name, family_name, mobile, phone, address, national_code, id_images, passport_images, etc.
  • Each claim is represented as an object with value and _meta fields, allowing tracking of verification, updates, and provenance uniformly.

  • Each claim:

    • May be present in some apps but absent in others
    • Can be optional in one app and mandatory in another
    • May require manual verification (e.g., by an admin) for use in specific apps
    # Example Claim Structure
    identity:
      name:
        value: "Ali"
        _meta: 
          verified: true
          verified_by: "[email protected]"
      national_code:
        value: "1234567890"
        _meta: 
          verified: true
          verified_by: "[email protected]"
    
    contact:
      email:
        value: "[email protected]"
        _meta: 
          verified: true
          last_updated: "2024-06-20"
    
    documents:
      avatar:
        url: "https://path/to/doc.jpg"
        _meta: 
          public: true
          status: "verified"
          verified_by: "[email protected]"
      passport:
        url: ["https://path/to/page1.jpg", "https://path/to/page2.jpg"]
        _meta: 
          status: "pending_verification"
          verified_by: null
          custom_meta_only_for_passport: "hi!"

3. Cross-Platform Compatibility

Seamless integration with Laravel, Filament, .NET, and future apps without vendor or language lock-in.

❓ Why This Matters

Current dashboards have:

  • Fragmented UX (duplicate registration/data entry)
  • No shared claims or user states
  • Inconsistent verification mechanisms

We aim to consolidate identity management while keeping authentication lightweight, and eventually allow for fine-grained access control per app and claim.

🧱 System Components

1. Identity Provider (IdP)

  • Manages login, registration, and session lifecycle
  • Implements OpenID Connect (OIDC) for token-based identity exchange
  • Examples: Keycloak, Authentik, Authelia, etc (See existing solutions for options)

2. User Identity Service

  • REST API to manage shared claims
  • Responsibilities:
    • Create, Edit, Store and expose profile claims
    • Track verification status
    • Handle admin/user-initiated verification flows
  • Audit sensitive changes
    • Claim editing, particularly for sensitive fields (e.g., passport, national_code, phone_verified), is governed by a role-based access control (RBAC) system within the User Identity Service. This system defines:
      • Which roles (e.g., admin, reviewer, superadmin) can view, edit, or verify specific claims
      • Which actions are permitted per role (e.g., edit vs. verify vs. override user input)
      • Audit logging for all admin-driven changes to sensitive claims
      • ⚠️ Admins do not bypass claim structure or verification flows β€” their permissions are scoped, auditable, and enforced by API boundaries.

3. External Validation Services

  • Used by the profile service to validate sensitive claims (e.g., phone number, ZIP code, national ID)
  • Examples: Twilio, Loqate

4. Client Applications

  • Authenticate via OIDC (using IdP)
  • Use the sub claim (subject identifier) as the consistent user ID across systems
  • Retrieve authorized claims from the Profile API
  • Claim access rules for each app (e.g., which claims App X can read or edit) are centrally defined and enforced by the User Identity Service.
  • Store only app-specific data locally (e.g., theme, app-specific data)

πŸ“¦ Responsibilities Breakdown

Component Responsibility
Identity Provider Authenticates users; issues tokens with user ID (sub)
User Identity Service Central API/Dashboard to manage and validate user claims
Validation Services External APIs to validate sensitive fields
Apps (A, B, etc.) Use OIDC to authenticate and query claims via User Identity Service API

βœ… Benefits

  • πŸ” Unified Authentication: Log in once, access all services
  • πŸ“¦ Centralized Data: One authoritative profile per user, accessible to all authorized apps
  • πŸ’Έ Efficient Verification: Expensive checks done once, reused system-wide
  • βš™οΈ Tech-Agnostic: Compatible with diverse stacks (Laravel, .NET, etc.)
  • 🌱 Scalable Design: Clean separation of concerns supports growth

πŸ”§ Suggested Endpoints (Profile API)

GET    /profile/{sub}              # Fetch full profile  
PATCH  /profile/{sub}              # Update claims (partial)  
POST   /profile/{sub}/verify:type  # Trigger verification (e.g., phone, document)  
GET    /profile/{sub}/verify:type  # Get verification status

🧠 Additional Notes

  • Apps may enforce custom rules (e.g., require mobile_verified == true before granting access).
  • Apps must not persist or override shared claims locally β€” temporary caching is allowed, but canonical data must come from the Profile API
  • Authorization should be claim-scoped per application, enforcing least-privilege access to profile data.

πŸ›  Suggested Stack

Component Stack Options
IdP Keycloak, Authentik, Authelia (OIDC)
User Identity Service Laravel
Validation Twilio, Loqate, PostGrid
Frontend Apps Laravel, Filament, React, .NET

πŸ—Ί Architecture Overview

graph TB
    
A[User]
X[Admin]
    
B[IdP: Authentication and Shared Session]


subgraph Applications
C1[App A]
C2[App B]
C3[App C]
end

D[User Identity Service]

E[External Validation APIs]

%% IdP communicates with User Identity Service
B <-->|internal api <br> sync sub| D

%% Login Flow
A -->|Login| B
X -->|Login| B

%% App Access (incl. Laravel)
B -->|sub| C1
B -->|sub| C2
B -->|sub| C3
B -->|sub| D

%% Claims
C1 -->|Read Claims| D
C2 -->|Read Claims| D
C3 -->|Read Claims| D


%% Processing
D -->|Validate Claims| E
Loading

⚠️ Anti-Patterns to Avoid

  1. ❌ Storing claim verification in local app DBs βœ… Always query the User Identity Service API

  2. ❌ Direct DB access to User Identity Service βœ… Use secure REST APIs with access controls

  3. ❌ Mixing incompatible auth protocols (e.g., SAML + OIDC) βœ… Standardize on OIDC across all apps for maintainability and interoperability

πŸ€” Lessons Learned / Critical Questions Answered

1. Is a separate User Identity Service necessary?

βœ… Yes, because:

  • we want dynamic claims creation
  • Claims are tied to verification workflows (internal or external)
  • Apps require filtered access to claims (e.g. only some can access sensitive documents)
  • Complex claims (e.g., passport) can contain multiple structured values (e.g., image URLs) along with rich metadata fields like verified, verified_by, or custom tags, all stored in a uniform schema.

2. Should we store data into OIDC tokens?

🚫 No.

  • The authentication layer exists solely to log the user in and maintain their identity across apps β€” it should not handle profile or verification data.
  • claims should be stored in our User Identity Service and be accessed through API
  • Login identifiers (e.g., mobile, username) may be included in OIDC claims for convenience, but all profile data must be sourced from the User Identity Service API.

3. How dynamic can the system be?

🎯 Goal: Make claim/app definitions dynamic via admin UI.

  • Define new claims
  • Assign claims to apps
  • Control who can view/edit/verify claims
  • After reconsideration, it’s likely better to treat claims as semi-static β€” predefined in updates Admins can control claim availability, visibility, and per-app requirements via the User Identity Service dashboard, rather than relying on fully dynamic definitions.

πŸ“˜ Terminology Notes

  • Claim: A unit of user profile data (e.g., email, phone_verified)
  • sub Claim: Unique user ID issued by IdP, used as primary key across apps
  • Refer to the Glossary for complete definitions.

*PS: IK existing solutions and glossary links are broken they are just some terms and links

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment