Skip to content

Allow oidc.providers to be resolved at runtime, like callbackUrl #48

Closed

Description

@vrilcode

Is there an existing issue that is already proposing this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe it

We’re building a multi-tenant app with one subdomain per tenant. All tenants sign in through the same identity provider, but each tenant has its own OIDC client, so different clientIds and secrets. Tenants are created at runtime and stored in our database.

The function form of callbackUrl already covers the subdomain part nicely, thanks for that! As far as we can tell, though, oidc.providers is a static map that’s read once at startup. So adding a tenant, or rotating a tenant’s client secret, would currently need a restart of the app. Please correct us if we missed an existing way to do this.

Describe the solution you'd like

providers: async (name, request) => {
  const tenant = await tenants.findByKey(name);
  return tenant
    ? { issuer: tenant.issuer, clientId: tenant.clientId, clientSecret: tenant.clientSecret }
    : undefined; // unknown provider → 404, like today
},

Drawbacks / open points we can think of (there are probably more we don’t see from the outside):

  • The config couldn’t be validated at startup anymore, so it would probably need to be validated when it’s resolved.
  • OidcClient instances seem to be cached per provider name. A changed config (e.g. a rotated secret) would need some way to refresh that cache.
  • It’s an extra lookup per login/callback, which apps could cache on their side if needed.

We’re very open to a different shape if something else fits the package’s design better.

Teachability, documentation, adoption, migration strategy

This would be purely additive: the existing Record form keeps working, so there’s no migration. In the docs, it could sit right after the paragraph about the callbackUrl function in "Add 'Sign in with Google'", maybe like:

"If your providers aren’t known at startup, for example one OIDC client per customer, pass a function as providers. start() and finish() call it with the provider’s name and the request; return the provider’s config, or undefined for a provider you don’t serve."

What is the motivation / use case for changing the behavior?

Self-service onboarding of new tenants without a redeploy. In B2B setups it’s quite common that each customer brings their own IdP client (or even their own IdP), so the list of providers grows with the customer base rather than being fixed in code.

As a workaround, we currently keep a reference to the providers object and add entries at runtime. It works in 0.1.1, but since it relies on internals we’d feel better with a supported way.

Activity

  1. kamilmysliwiec commented on Oct 13, 2026

    @kamilmysliwiec
    Member

    lets track this here #52

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions