authentication #882

Closed
opened 2026-03-28 04:29:31 +00:00 by mfreeman451 · 1 comment
Owner

Imported from GitHub.

Original GitHub issue: #2542
Original author: @mfreeman451
Original URL: https://github.com/carverauto/serviceradar/issues/2542
Original created: 2026-01-27T13:03:32Z


Issue: Implement Instance-Level Dynamic Authentication (SSO, OIDC, and SAML)

Description

Currently, the application relies on a single hardcoded admin user. We need to allow instance owners to configure their own Identity Providers (IdP) through the UI. Because each tenant has a dedicated application instance, the authentication configuration will be specific to that instance but stored in the database.

This will enable users to log in via modern OIDC (Google, Azure AD) or legacy Enterprise SAML.

User Story

As an Instance Admin, I want to configure my organization's SSO provider via the UI so that my users can log in using their corporate credentials without me having to manually edit configuration files or restart the server.


Technical Requirements

1. Database Schema (Instance-Specific)

We need a table to store the SSO configuration for the current instance in the platform schema

  • Create auth_settings table:
    • provider_type: :oidc or :saml
    • client_id / client_secret: (Encrypted via cloak or similar)
    • idp_metadata_url: (For OIDC discovery or SAML)
    • saml_issuer: The "Entity ID" for the service provider.
    • is_enabled: Boolean to toggle SSO on/off.

2. Runtime Configuration Loader

Since Elixir/Phoenix libraries (like ueberauth) typically expect compile-time config, we need to load settings from the database at the moment the user initiates a login.

  • Implement a Dynamic Config Fetcher: A module that reads auth_settings from the DB and merges them into the Ueberauth configuration at runtime.
  • JIT (Just-In-Time) User Provisioning: When a user successfully authenticates via SSO, if they don't exist in the local users table, create them and assign default roles.

3. Admin Configuration UI (LiveView)

A dedicated settings page for instance administrators.

  • Protocol Toggle: Choice between "Standard (Email/Pass)", "OpenID Connect", and "SAML".
  • SAML Configuration:
    • Fields for IdP Metadata URL or Metadata XML.
    • Display the ACS (Assertion Consumer Service) URL that the admin must provide to their IdP (e.g., https://tenant.myapp.com/sso/sp/consume).
  • OIDC Configuration:
    • Fields for Client ID, Client Secret, and Discovery URL.
  • Validation: A "Test Configuration" flow to ensure the app can successfully communicate with the IdP before locking out password-based login.

4. The Login Flow

  • Modify the Login Page to show an "Enterprise Login" button if SSO is enabled.
  • SSO Redirect: Route the user to the configured provider.
  • Callback Handling: Implement the controller logic to handle the returning JWT (OIDC) or XML Assertion (SAML), verify the signature, and establish the user session.

Task List

  • Migrations: Create auth_settings table.
  • Encryption: Ensure client_secret and SAML private keys are encrypted at rest.
  • SAML Support: Integrate ueberauth_saml for XML-based enterprise auth.
  • OIDC Support: Integrate ueberauth_oidcc for modern JSON-based enterprise auth.
  • UI: Build the "Authentication" settings tab in the Admin UI.
  • Session Management: Ensure SSO-initiated sessions follow the same RBAC rules as local users.

Security Considerations

  • SAML Signature Validation: Must strictly validate the IdP's certificate to prevent assertion spoofing.
  • Schema Isolation: Ensure that even if auth is shared, the User record is provisioned into the correct tenant-specific context as defined by the instance's DB connection.
  • Fallback Mechanism: Ensure the initial local admin can still log in via a "backdoor" or password if the SSO configuration is misconfigured (to avoid permanent lockouts).

Success Criteria

  1. An admin can configure Okta/Azure via the UI.
  2. A user can log in without a password via their corporate dashboard.
  3. The system automatically creates a local record for the user on their first successful login.
Imported from GitHub. Original GitHub issue: #2542 Original author: @mfreeman451 Original URL: https://github.com/carverauto/serviceradar/issues/2542 Original created: 2026-01-27T13:03:32Z --- ## Issue: Implement Instance-Level Dynamic Authentication (SSO, OIDC, and SAML) ### Description Currently, the application relies on a single hardcoded admin user. We need to allow instance owners to configure their own Identity Providers (IdP) through the UI. Because each tenant has a dedicated application instance, the authentication configuration will be specific to that instance but stored in the database. This will enable users to log in via modern OIDC (Google, Azure AD) or legacy Enterprise SAML. ### User Story > As an **Instance Admin**, I want to configure my organization's SSO provider via the UI so that my users can log in using their corporate credentials without me having to manually edit configuration files or restart the server. --- ### Technical Requirements #### 1. Database Schema (Instance-Specific) We need a table to store the SSO configuration for the current instance in the `platform` schema - [ ] Create `auth_settings` table: - `provider_type`: `:oidc` or `:saml` - `client_id` / `client_secret`: (Encrypted via `cloak` or similar) - `idp_metadata_url`: (For OIDC discovery or SAML) - `saml_issuer`: The "Entity ID" for the service provider. - `is_enabled`: Boolean to toggle SSO on/off. #### 2. Runtime Configuration Loader Since Elixir/Phoenix libraries (like `ueberauth`) typically expect compile-time config, we need to load settings from the database at the moment the user initiates a login. - [ ] Implement a **Dynamic Config Fetcher**: A module that reads `auth_settings` from the DB and merges them into the `Ueberauth` configuration at runtime. - [ ] **JIT (Just-In-Time) User Provisioning:** When a user successfully authenticates via SSO, if they don't exist in the local `users` table, create them and assign default roles. #### 3. Admin Configuration UI (LiveView) A dedicated settings page for instance administrators. - [ ] **Protocol Toggle:** Choice between "Standard (Email/Pass)", "OpenID Connect", and "SAML". - [ ] **SAML Configuration:** - Fields for **IdP Metadata URL** or **Metadata XML**. - Display the **ACS (Assertion Consumer Service) URL** that the admin must provide to their IdP (e.g., `https://tenant.myapp.com/sso/sp/consume`). - [ ] **OIDC Configuration:** - Fields for `Client ID`, `Client Secret`, and `Discovery URL`. - [ ] **Validation:** A "Test Configuration" flow to ensure the app can successfully communicate with the IdP before locking out password-based login. #### 4. The Login Flow - [ ] Modify the Login Page to show an "Enterprise Login" button if SSO is enabled. - [ ] **SSO Redirect:** Route the user to the configured provider. - [ ] **Callback Handling:** Implement the controller logic to handle the returning JWT (OIDC) or XML Assertion (SAML), verify the signature, and establish the user session. --- ### Task List - [ ] **Migrations:** Create `auth_settings` table. - [ ] **Encryption:** Ensure `client_secret` and SAML private keys are encrypted at rest. - [ ] **SAML Support:** Integrate `ueberauth_saml` for XML-based enterprise auth. - [ ] **OIDC Support:** Integrate `ueberauth_oidcc` for modern JSON-based enterprise auth. - [ ] **UI:** Build the "Authentication" settings tab in the Admin UI. - [ ] **Session Management:** Ensure SSO-initiated sessions follow the same RBAC rules as local users. ### Security Considerations * **SAML Signature Validation:** Must strictly validate the IdP's certificate to prevent assertion spoofing. * **Schema Isolation:** Ensure that even if auth is shared, the `User` record is provisioned into the correct tenant-specific context as defined by the instance's DB connection. * **Fallback Mechanism:** Ensure the initial local admin can still log in via a "backdoor" or password if the SSO configuration is misconfigured (to avoid permanent lockouts). ### Success Criteria 1. An admin can configure Okta/Azure via the UI. 2. A user can log in without a password via their corporate dashboard. 3. The system automatically creates a local record for the user on their first successful login.
Author
Owner

Imported GitHub comment.

Original author: @mfreeman451
Original URL: https://github.com/carverauto/serviceradar/issues/2542#issuecomment-3809172483
Original created: 2026-01-28T06:02:23Z


ADDENDUM:

Issue: Implement Multi-Mode Authentication (SSO, OIDC, SAML, and Proxy JWT)

Description

We need to support diverse enterprise authentication patterns. While some instances will connect directly to an IdP (OIDC/SAML), others will sit behind an API Gateway (like Kong) that handles authentication upstream and passes a JWT to our application.

Technical Requirements

1. Database Schema Update

Expand the auth_settings table to support "Passive" (Proxy) and "Active" (SAML/OIDC) modes.

  • mode: Enum (:active vs :passive)
  • type: Enum (:oidc, :saml, :proxy_jwt)
  • config: JSONB field to store:
    • For OIDC/SAML: Client IDs, Secrets, Metadata URLs.
    • For Proxy JWT: Public Key (PEM), Expected Issuer, and Header Name.

2. Logic for "Proxy JWT" (Kong Support)

For instances behind a gateway, the app will not redirect to a login page.

  • JWT Validation Plug:
    • Extract JWT from a configurable header.
    • Verify signature using the stored Public Key/JWKS.
    • Verify exp (expiration) and iss (issuer) claims.
  • User Extraction: Map JWT claims (e.g., sub or email) to the local User record.
  • Internal Auth Bypass: When proxy_jwt is active, the standard login page should be disabled or hidden.

3. Logic for "Active SSO" (OIDC/SAML)

For instances connecting directly to an IdP.

  • OIDC Flow: Use ueberauth_oidcc to handle the redirect and code exchange.
  • SAML Flow: Use ueberauth_saml to handle the XML-based redirection and assertion consumption.
  • Dynamic Config: Load client_id and metadata from the DB at the start of the request.

4. Admin UI (LiveView)

  • Mode Selection: Admin chooses "Direct SSO" or "Gateway/Proxy Auth."
  • Proxy Settings:
    • Input for Public Key (PEM format).
    • Input for Header Name (Default: Authorization).
  • Direct Settings:
    • Input for OIDC/SAML credentials as previously defined.

5. User Provisioning (JIT)

  • Regardless of the method (SAML or Kong JWT), the system must check if the user exists in the local database schema.
  • If not, automatically create the user based on the claims provided in the token (Just-In-Time provisioning).

Task List

  • Migration: Create/Update auth_settings table.
  • Security: Implement JWT signature verification using JOSE.
  • Plug: Create AppWeb.Plugs.GatewayAuth to intercept Kong headers.
  • Strategy: Update AppWeb.AuthController to handle multiple Ueberauth strategies dynamically.
  • UI: Build the Admin "Auth Settings" tab.

Success Criteria

  1. Scenario A (SAML): User clicks "Login," goes to Okta, comes back, and is logged in.
  2. Scenario B (Kong): Admin pastes Kong's Public Key into the UI. Any request with a valid JWT from Kong is automatically logged in without ever seeing a login screen.
  3. Local Sync: In both scenarios, a User record is created in the database to track permissions and history.

Pro-Tip for the Kong setup:

When Kong is handling auth, it often passes the user's details in a header like X-User-Email or X-User-Id. However, always verify the JWT signature inside your Phoenix app. If you just trust the header X-User-Email without a signature, a clever user could bypass Kong and send that header directly to your app to impersonate anyone.

Imported GitHub comment. Original author: @mfreeman451 Original URL: https://github.com/carverauto/serviceradar/issues/2542#issuecomment-3809172483 Original created: 2026-01-28T06:02:23Z --- ADDENDUM: ## Issue: Implement Multi-Mode Authentication (SSO, OIDC, SAML, and Proxy JWT) ### Description We need to support diverse enterprise authentication patterns. While some instances will connect directly to an IdP (OIDC/SAML), others will sit behind an API Gateway (like Kong) that handles authentication upstream and passes a JWT to our application. ### Technical Requirements #### 1. Database Schema Update Expand the `auth_settings` table to support "Passive" (Proxy) and "Active" (SAML/OIDC) modes. - [ ] `mode`: Enum (`:active` vs `:passive`) - [ ] `type`: Enum (`:oidc`, `:saml`, `:proxy_jwt`) - [ ] `config`: JSONB field to store: - **For OIDC/SAML:** Client IDs, Secrets, Metadata URLs. - **For Proxy JWT:** Public Key (PEM), Expected Issuer, and Header Name. #### 2. Logic for "Proxy JWT" (Kong Support) For instances behind a gateway, the app will not redirect to a login page. - [ ] **JWT Validation Plug:** - Extract JWT from a configurable header. - Verify signature using the stored Public Key/JWKS. - Verify `exp` (expiration) and `iss` (issuer) claims. - [ ] **User Extraction:** Map JWT claims (e.g., `sub` or `email`) to the local User record. - [ ] **Internal Auth Bypass:** When `proxy_jwt` is active, the standard login page should be disabled or hidden. #### 3. Logic for "Active SSO" (OIDC/SAML) For instances connecting directly to an IdP. - [ ] **OIDC Flow:** Use `ueberauth_oidcc` to handle the redirect and code exchange. - [ ] **SAML Flow:** Use `ueberauth_saml` to handle the XML-based redirection and assertion consumption. - [ ] **Dynamic Config:** Load `client_id` and `metadata` from the DB at the start of the request. #### 4. Admin UI (LiveView) - [ ] **Mode Selection:** Admin chooses "Direct SSO" or "Gateway/Proxy Auth." - [ ] **Proxy Settings:** - Input for **Public Key (PEM format)**. - Input for **Header Name** (Default: `Authorization`). - [ ] **Direct Settings:** - Input for OIDC/SAML credentials as previously defined. #### 5. User Provisioning (JIT) - [ ] Regardless of the method (SAML or Kong JWT), the system must check if the user exists in the local database schema. - [ ] If not, automatically create the user based on the claims provided in the token (Just-In-Time provisioning). --- ### Task List - [ ] **Migration:** Create/Update `auth_settings` table. - [ ] **Security:** Implement JWT signature verification using `JOSE`. - [ ] **Plug:** Create `AppWeb.Plugs.GatewayAuth` to intercept Kong headers. - [ ] **Strategy:** Update `AppWeb.AuthController` to handle multiple Ueberauth strategies dynamically. - [ ] **UI:** Build the Admin "Auth Settings" tab. ### Success Criteria 1. **Scenario A (SAML):** User clicks "Login," goes to Okta, comes back, and is logged in. 2. **Scenario B (Kong):** Admin pastes Kong's Public Key into the UI. Any request with a valid JWT from Kong is automatically logged in without ever seeing a login screen. 3. **Local Sync:** In both scenarios, a `User` record is created in the database to track permissions and history. --- ### Pro-Tip for the Kong setup: When Kong is handling auth, it often passes the user's details in a header like `X-User-Email` or `X-User-Id`. However, **always** verify the **JWT signature** inside your Phoenix app. If you just trust the header `X-User-Email` without a signature, a clever user could bypass Kong and send that header directly to your app to impersonate anyone.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
carverauto/serviceradar#882
No description provided.