Skip to content

Identity Providers

Broch delegates authentication to your identity provider. The Broch server is the sole OAuth client — a confidential client registered as a Web Application in your IdP. End users never interact with your IdP directly from the browser or CLI. All OAuth flows are brokered by the server, which issues its own Broch tokens to clients.

This means:

  • One app registration per deployment (not per user or per client)
  • A client secret is required and kept on the server — never exposed to browsers or CLI
  • Redirect URIs point to the Broch server, not to clients
  • Your IdP’s MFA, conditional access, and group policies apply automatically

Why this is simpler to configure

One app registration covers every Broch client — web app, CLI, and any future client. You configure one redirect URI (your server URL), one client secret, and one set of scopes. There is no per-device enrollment, no per-client OAuth flow, and no IdP changes required when new clients are added or existing ones are updated. One registration to set up, one to audit, one secret to rotate.

Why this is more secure than public clients

Public clients (SPAs and native apps that handle OAuth directly) cannot keep a client secret. This forces them to rely on PKCE and short-lived tokens stored in browser memory or local storage — both reachable by malicious scripts. The IETF OAuth 2.0 Security Best Current Practice (RFC 9700) explicitly recommends against issuing tokens to public clients when a confidential client is feasible.

The Backend for Frontend (BFF) pattern addresses this by moving all token handling to the server. Tokens are never sent to the browser; the browser holds only a session cookie. This eliminates the XSS token-theft risk entirely. The OAuth 2.0 for Browser-Based Apps specification recommends the BFF pattern for any application that needs to call APIs on behalf of a user.

You will need your Broch server URL (e.g., https://tunnels.company.com) before configuring your IdP — it is used as the redirect URI and, for some providers, the API audience. Complete your domain and DNS setup first.

Broch works with any OIDC-compatible provider. Step-by-step guides are available for these popular ones:

  • Auth0 — Auth0 with RBAC and post-login actions
  • Entra ID — Azure Entra ID (formerly Azure AD) with app roles
  • Okta — Okta with groups and authorization server configuration

For any other provider, follow the general setup below. Contact [email protected] if you need help.

If your IdP is not listed above, follow these steps.

In your IdP, create a new application registration of type Web Application (or equivalent: Regular Web App, confidential client, server-side app). Configure it with:

  • Redirect URI: https://tunnels.company.com/auth/callback (replace with your wildcard hostname)
  • Grant type: Authorization Code
  • Token endpoint authentication: Client secret (not PKCE-only)
  • Scopes: openid, profile, email, offline_access

Your IdP must expose an OIDC discovery document at {issuer}/.well-known/openid-configuration. The access token must include an email claim. If you want admin access, the token must also include a roles or groups claim matching your AUTHENTICATION__ADMINROLES value.

In your Broch environment, set:

Terminal window
# Generic OIDC — standard openid/profile/email scopes, no named-provider quirks
AUTHENTICATION__PROVIDER=Oidc
# Your IdP's issuer URL — the base that serves /.well-known/openid-configuration
AUTHENTICATION__AUTHORITY=https://your-idp.example.com
AUTHENTICATION__CLIENTID=your-client-id
AUTHENTICATION__CLIENTSECRET=your-client-secret
AUTHENTICATION__ADMINROLES=your-admin-role
# Optional: request ADDITIONAL scopes (e.g. a resource/API scope your IdP needs).
# AUTHENTICATION__SCOPES is additive — Broch always requests openid, profile, email,
# and offline_access; anything you set here is appended, never substituted.
# AUTHENTICATION__SCOPES=api://your-resource/.default

Broch always requests openid, profile, email, and offline_accessopenid is what makes the IdP issue the id_token Broch authenticates on, and email is the user identifier. You don’t configure these; AUTHENTICATION__SCOPES only adds extra scopes on top.

The server fetches {AUTHENTICATION__AUTHORITY}/.well-known/openid-configuration at startup to discover the authorization, token, and revocation endpoints. Setting AUTHENTICATION__AUTHORITY overrides all provider-specific authority derivation.

Recovering From a Broken IdP Configuration

Section titled “Recovering From a Broken IdP Configuration”

IdP configuration saved through the admin UI persists to the database and overrides the AUTHENTICATION__* environment values on the next restart. That creates one failure mode worth knowing in advance: if the persisted client secret expires or is rotated at the IdP (Entra enforces secret expiry of 24 months or less), every sign-in fails with invalid_client — including the admin sign-in you’d use to fix it. Updating the environment variable doesn’t help, because the persisted value still wins.

The break-glass is BROCH_AUTH_CONFIG_RESET:

BROCH_AUTH_CONFIG_RESET=true

Set it and restart the server. At boot, Broch clears the persisted IdP configuration and falls back to your AUTHENTICATION__* environment values — or first-run state if none are set. Sign in, re-enter the corrected configuration in the admin UI if you manage it there, then remove the variable: while it is set, every restart clears the persisted configuration again.

The server log names this lever when the IdP rejects the client credentials, so you’ll find it again under pressure: look for invalid_client in the server output.