Supported Providers

OpenID Connect (OIDC)

Dev Portal supports any identity provider that implements the OpenID Connect protocol via the generic openid provider type. This includes Okta, Keycloak, Authentik, Ory, ZITADEL, AWS Cognito, Google Identity, and most enterprise IdPs.

Configuration

Add the authentication property to your Dev Portal configuration:

TypeScriptzudoku.config.ts
{ // ... authentication: { type: "openid", clientId: "<your-client-id>", issuer: "<the-issuer-url>", scopes: ["openid", "profile", "email"], // Optional }, // ... }
OptionRequiredDescription
clientIdYesThe OAuth client ID issued by your provider.
issuerYesThe issuer URL. Dev Portal discovers endpoints from <issuer>/.well-known/openid-configuration.
scopesNoScopes to request. Defaults to ["openid", "profile", "email"].
allowInsecureRequestsNoAllow discovery and token requests against an http:// issuer. Defaults to false. Intended only for local development — never enable this in production.

Provider Setup

Register Dev Portal as a public SPA / single page application client in your identity provider and set:

  • Callback / Redirect URI to https://your-site.com/oauth/callback
  • For local development, add http://localhost:3000/oauth/callback
  • If your provider supports wildcards, add https://*.your-domain.com/oauth/callback for preview environments
  • Add your site origin to the list of allowed CORS origins
  • Enable the Authorization Code grant with PKCE and the Refresh Token grant

Okta

  1. In the Okta admin console go to Applications → Applications → Create App Integration.
  2. Select OIDC - OpenID Connect and Single Page Application.
  3. Set Sign-in redirect URIs to https://your-site.com/oauth/callback (add http://localhost:3000/oauth/callback for local development).
  4. Under Assignments, assign the users or groups that should have access.
  5. After creating the app, copy the Client ID. Your issuer is your Okta domain, for example https://your-tenant.okta.com or a custom authorization server like https://your-tenant.okta.com/oauth2/default.
  6. Under Security → API → Trusted Origins, add your site origin for both CORS and Redirect.
TypeScriptzudoku.config.ts
{ authentication: { type: "openid", clientId: "<your-okta-client-id>", issuer: "https://your-tenant.okta.com/oauth2/default", scopes: ["openid", "profile", "email"], }, }

Keycloak

Use the realm issuer URL:

TypeScriptzudoku.config.ts
{ authentication: { type: "openid", clientId: "zudoku", issuer: "https://keycloak.example.com/realms/<your-realm>", }, }

In the realm, create a client with Client type OpenID Connect, Access type public, and enable Standard Flow (Authorization Code).

Verifying the Issuer

You can confirm your issuer URL is correct by opening <issuer>/.well-known/openid-configuration in a browser. It should return a JSON document listing authorization_endpoint, token_endpoint, userinfo_endpoint, and jwks_uri.

Customizing Sign-up

By default Register and Sign in both call the OIDC authorize endpoint, so users land on the same login page. Two options change that:

TypeScriptzudoku.config.ts
{ authentication: { type: "openid", clientId: "<your-client-id>", issuer: "<the-issuer-url>", // Send Register to a separate URL (absolute → external redirect, relative → in-app navigate) signUp: { url: "/register" }, // Or pass extra params to the authorize URL on sign-up only (e.g. Keycloak) signUp: { authorizationParams: { kc_action: "register" } }, // Hide Register UI entirely. Visual only — still configure your IdP to block sign-ups. disableSignUp: true, }, }

When disableSignUp is true, the Register button on the protected-route login dialog is hidden and /signup shows an "Invitation required" page.

User Profile

After sign-in Dev Portal calls the provider's UserInfo endpoint and reads name, email, picture, and email_verified from the response. Map these claims in your provider if they are not emitted by default.

Local Development with an HTTP Issuer

oauth4webapi (the library Dev Portal uses under the hood) rejects issuers that don't use https:// by default, since OIDC requires TLS in production. If you're running an identity provider locally over plain HTTP (e.g. a dockerized Keycloak on http://localhost:9090), set allowInsecureRequests to true so discovery and token requests are allowed to use http://:

TypeScriptzudoku.config.ts
{ authentication: { type: "openid", clientId: "<your-client-id>", issuer: "http://localhost:9090/auth/realms/<your-realm>", allowInsecureRequests: true, }, }

Only enable this for local development. Never set allowInsecureRequests to true against a production issuer.

Troubleshooting

  • Discovery fails: verify <issuer>/.well-known/openid-configuration resolves and matches the issuer value in the document.
  • CORS errors on token / userinfo: add your site origin to the provider's allowed origins.
  • Redirect URI mismatch: the URI registered with the provider must match the Dev Portal origin exactly, including protocol and port.
  • Missing profile fields: ensure profile and email scopes are granted and that the provider includes name, email, and picture claims in the UserInfo response.
Last modified on