Loading…
Loading…
Manage per-tenant Identity Provider (IdP) configurations for OIDC, SAML, and IAP. Store and retrieve IdP settings, including client credentials and
The IdpConfigRepository is a data access component responsible for persisting and retrieving Identity Provider (IdP) configurations. It manages settings for OIDC, SAML, and IAP providers on a per-tenant, per-installation basis, storing them in the s2r_idp_config database table.
This repository solves the problem of integrating the platform with external authentication providers. It acts as the canonical store for all connection details, such as client IDs, issuer URLs, and encrypted client secrets. Service-layer components call this repository to create, read, and update IdP settings, which in turn drive the platform's authentication and authorization mechanisms.
A key architectural concept is the platform's "authentication posture." The number of active IdP configurations for an entire installation determines whether the platform operates in "protected mode" (enforcing RBAC) or "open mode" (no authentication enforced). If at least one active IdP configuration exists for an installation, the platform is in protected mode. If there are zero, it falls back to open mode.
All operations are strictly tenant-scoped to ensure data isolation. The repository handles encrypted client secrets as opaque envelopes, with encryption and decryption being the responsibility of a higher-level service.
The repository interacts with a single database table, s2r_idp_config. Its operations are designed to be atomic and preserve a complete audit history.
Data access is strictly controlled by a multi-layered tenancy model:
s2r_tenant_isolation policy on the s2r_idp_config table.TENANT_SCOPE SQL clause. This ensures that even connections with RLS-bypassing privileges are correctly scoped to the application's current tenant.TENANT_SCOPE includes a REQUIRE_BOUND_TENANT_SQL check. If a database connection is used without a tenant ID bound to it, the query will fail with an S2R-TENANCY-UNBOUND error rather than defaulting to another tenant's data or returning no data.tenant_id column is automatically populated by the database based on the connection's settings during an INSERT.idp_directory_tenant_id field represents an external identifier for a tenant within the upstream IdP system and is distinct from the platform's internal tenant ID.When creating or updating an IdP configuration via upsertActive or upsertIap, the repository follows a two-step process to ensure atomicity and maintain an audit trail. This prevents having more than one active configuration for a given provider.
sequenceDiagram
participant Service as "Service Layer"
participant Repo as "IdpConfigRepository"
participant DB as "Database (s2r_idp_config)"
Service->>Repo: upsertActive(installationId, provider, ...);
Note over Repo: Begins upsert process
Repo->>DB: UPDATE s2r_idp_config SET is_active = false WHERE installation_id = ? AND provider = ? AND is_active = true;
Note right of DB: Deactivates any existing active config,<br/>preserving the row for audit.
Repo->>DB: INSERT INTO s2r_idp_config (...) VALUES (...);
Note right of DB: Inserts a new row with the new config,<br/>marked as is_active = true.
DB-->>Repo: Returns new config's UUID
Repo-->>Service: Returns new config's UUIDDeactivating a configuration via the deactivate method performs only the first step of this process. The old configuration remains in the database with is_active set to false.
The countActive method is an exception to the strict tenant-scoping rule. It calls a SECURITY DEFINER database function, s2r_idp_config_active_count, which intentionally reads across all tenants for a given installation. This is critical for determining the installation-wide authentication posture. If the count were tenant-scoped, a tenant without an IdP configuration could cause the entire installation to incorrectly switch to "open mode." This method returns only a count, never the configuration data of another tenant.
Identity-Aware Proxy (IAP) configurations are a special case. They are identified by the provider name iap.
iap_members.upsertIap method creates these configurations. If an empty list is provided for iapMembers, the existing IAP configuration is deactivated, and no new active one is created. This effectively disables the IAP gate for the installation.The repository exposes the following methods for managing IdP configurations.
| Method Signature | Description |
|---|---|
List<IdpConfigRow> findActive(UUID installationId) | Finds all active IdP configurations for a given installation ID, scoped to the current tenant. Returns an empty list if installationId is null. |
List<IdpConfigRow> findAll(UUID installationId) | Finds all IdP configurations (both active and inactive) for a given installation ID, scoped to the current tenant. Results are ordered by is_active descending. Returns an empty list if installationId is null. |
Optional<IdpConfigRow> findActiveByProvider(UUID installationId, String provider) | Finds the single active IdP configuration for a specific provider and installation ID, scoped to the current tenant. Returns an empty Optional if not found or if arguments are null. |
UUID upsertActive(UUID installationId, String provider, ..., boolean isAutoProvisioned) | Creates or updates an IdP configuration. It deactivates any previous active configuration for the provider and inserts a new active one. Returns the UUID of the new configuration row. |
void deactivate(UUID installationId, String provider, String updatedBy) | Deactivates the active IdP configuration for the specified provider and installation ID. The row is kept for auditing with is_active set to false. |
int countActive(UUID installationId) | Counts all active IdP configurations for an installation across all tenants. This method bypasses tenant scoping to determine the installation-wide authentication posture. Returns 0 if installationId is null. |
UUID upsertIap(UUID installationId, String displayName, List<String> iapMembers, ...) | Creates or updates the special IAP configuration. If iapMembers is null or empty, it deactivates the existing IAP configuration and returns null. Otherwise, it creates a new active IAP configuration and returns its UUID. |
List<String> findActiveIapMembers(UUID installationId) | Retrieves the list of members (iap_members) from the active IAP configuration for the given installation. Returns an empty list if no active IAP configuration exists. |
NOTE
The upsertActive method has several overloads for backward compatibility. The full signature accepts all fields, including metadataXml for SAML and the isAutoProvisioned flag.
IdpConfigRowThis record represents a single row from the s2r_idp_config table.
| Field | Type | Description |
|---|---|---|
id | UUID | The unique identifier for the configuration row. |
installationId | UUID | The identifier of the installation this configuration belongs to. |
provider | String | The name of the identity provider (e.g., oidc, saml, iap). |
displayName | String | The user-facing name for this IdP configuration. |
issuerUrl | String | The issuer URL of the OIDC or SAML provider. |
clientId | String | The client ID for authenticating with the IdP. |
clientSecretEnvelope | String | The encrypted JSON envelope containing the client secret. The repository treats this as an opaque value. |
idpDirectoryTenantId | String | The tenant identifier within the external IdP system. Not to be confused with the platform's internal tenant ID. |
allowedEmailDomains | List<String> | A list of email domains that are permitted to use this IdP. |
isActive | boolean | true if this configuration is the currently active one for its provider; false otherwise. |
createdAt | OffsetDateTime | The timestamp when the configuration row was created. |
updatedAt | OffsetDateTime | The timestamp when the configuration row was last updated. |
updatedBy | String | The identifier of the user or process that last updated the row. |
metadataXml | String | The full SAML metadata XML document, if applicable. |
isAutoProvisioned | boolean | true if the configuration was created by an automated wizard (e.g., via Microsoft Graph or Okta Apps API); false if values were entered manually. |
iapMembers | List<String> | For IAP configurations only. A list of members allowed access. |
iapAccessDeniedMessage | String | For IAP configurations only. An optional message to display when access is denied. |
S2R-TENANCY-UNBOUND ErrorIf a query fails with an error code of S2R-TENANCY-UNBOUND, it means a repository method was called using a database connection that did not have a tenant ID bound to it. This is a security feature to prevent accidental cross-tenant data access. Ensure the service calling the repository has properly established the tenant context on its database connection.
Most methods perform null checks on their installationId and provider arguments. If a required identifier is null, the methods will typically return an empty result (e.g., List.of(), Optional.empty(), or 0) instead of throwing an exception.
Calling upsertIap with a null or empty iapMembers list will deactivate the IAP gate for the installation. This is intentional behavior. If this was not the last active IdP for the installation, other IdP-based authentication will still be enforced. If it was the last active IdP, the installation may revert to "open mode."
deactivate and upsert methods update the is_active flag rather than deleting rows. This behavior is related to the system's AuditRepository.clientSecretEnvelope field is handled by the CredentialsCipher service, which is responsible for all encryption and decryption operations. This repository only stores and retrieves the opaque, encrypted value.