Altien unbolts Mike from a single login system

The fork rewires authentication so Mike can sit behind whichever identity system a firm already runs.

securityintegration

Out of the box, Mike assumes everyone signs in through Supabase, a hosted user-and-database service. Altien's team has pulled that assumption apart and turned the login layer into a swappable slot. The original Supabase path still works untouched, but two alternatives now live alongside it: Microsoft's Entra (the corporate identity system most large firms already use for Office and Teams), and a lightweight local login for developers running Mike on a laptop.

The Entra path is the interesting one for in-house teams. It validates corporate tokens against the firm's own tenant, maps existing Microsoft security groups to Mike's admin and member roles, and can auto-onboard a tenant on first sign-in. There's also a guardrail that refuses access for tenants marked suspended or pending. The router is in place but not yet switched on in the running server.

So what Legal-ops leads evaluating an OSS legal-AI deployment should care: this is the difference between standing up a parallel user directory and plugging Mike into the SSO their firm already trusts.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

3 commits from Altien/mikeOssAzure, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
bfee639b refactor(auth): extract AuthProvider interface and Supabase provider Allen Morgan 2026-05-08 ↗ GitHub
commit body
Provider-neutral AuthPrincipal + AuthValidationResult types in
auth/types.ts. Existing inline Supabase validation extracted to
auth/providers/supabase.ts. Middleware dispatches on AUTH_PROVIDER env
var, defaulting to 'supabase'; unknown values return 500.

Zero behaviour change when AUTH_PROVIDER is unset or 'supabase'.
Downstream routes still receive res.locals.userId / userEmail / token;
res.locals.principal is added as the canonical surface.
f9eb061c feat(auth): Entra ID provider with JWKS + tenant lifecycle + roles Allen Morgan 2026-05-08 ↗ GitHub
commit body
Adds the Entra branch of the auth boundary established in the previous
refactor. Components:

  * lib/auth/providers/entra.ts  - JWT validation against the tenant's
    JWKS (5-minute cache), with both v1.0 and v2.0 issuer + audience
    shapes accepted, exp/nbf checks, and a fallback chain for the
    email and display-name claims that Entra optionally populates.

  * lib/auth/roles.ts            - Maps Entra group OIDs to app roles
    via ENTRA_ADMIN_GROUP_IDS / ENTRA_MEMBER_GROUP_IDS env vars.
    TenantAdmin includes Member by inheritance.

  * middleware/tenantAccess.ts   - Entra-only tenant lifecycle: looks
    up the principal's tenant in the tenants table, denies UNKNOWN /
    PENDING / SUSPENDED tenants, and enforces group-to-role mapping.
    Auto-onboards when TENANT_ONBOARDING_MODE=auto.  No-ops for any
    other auth provider so non-Entra deployments are unaffected.

  * middleware/requireRole.ts    - Tiny role guard that 403s when the
    principal lacks the requested role.

  * Auth middleware now dispatches "entra" alongside "supabase" and
    routes every authenticated request through tenantAccess (no-op for
    non-Entra) after upserting the user_profiles row from the IdP
    claims.  upsertUserProfile back-fills display_name only when null
    so the user's own edits aren't clobbered on every request.
ec310e59 feat(auth): local HS256 provider + login/OpenID routes Allen Morgan 2026-05-08 ↗ GitHub
commit body
Adds the third arm of the auth boundary - a local HS256 provider for
the docker-compose dev stack - plus the routes that drive provider-
flow logins:

  * lib/auth/providers/local.ts - stdlib-only HS256 verification.
    No new dependency.  When PostgREST eventually moves to JWKS, this
    becomes a thin jose wrapper and call sites stay the same.

  * routes/auth.ts - three families of routes:
      - POST /local-login        : mints an HS256 token for a stub email
                                   when AUTH_PROVIDER=local
      - GET  /providers          : lists available IdPs for the frontend
      - GET  /logout             : provider-aware sign-out (entra clears
                                   the IdP session, others bounce to /login)
      - GET  /select-provider, /login-provider/:id, /openid-callback/:id
                                 : Entra OIDC code-flow with HMAC-signed
                                   state cookie

  * Middleware now dispatches the "local" branch.

The router itself is added to the codebase but not yet mounted on the
Express app - the index.ts wiring (and the API prefix shift) lands in a
later commit so this one stays focused on the provider boundary.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-189.md from inside the repo you want the changes in.

⬇ Download capture-thread-189.md