Skip to content

Provider-only sign-in mode: one sign-in policy per surface, break-glass accounts - #907

Merged
KrzysztofPajak merged 9 commits into
developfrom
feature/oidc-provider-only-core
Oct 14, 2026
Merged

KrzysztofPajak merged 9 commits into
developfrom
feature/oidc-provider-only-core

Conversation

@KrzysztofPajak

Copy link
Copy Markdown
Member

Resolves no public issue
Type: feature

Issue

Installations that run GrandNode behind a company single sign-on need the identity provider to be the only way to sign in. Today every password path (storefront, Store/Vendor/Admin panels, Frontend API, legacy API users, password recovery, cookie validation, token refresh) decides with IExternalSignInPolicy.RequiredProvider, which knows nothing about where the password is used and cannot keep a short list of emergency administrator accounts.

First of four stacked pull requests for the provider-only sign-in mode (core → web → plugin → guide).

Solution

  • OidcLogin:SignInMode = Mixed (default, unchanged behaviour) | ProviderOnly, and OidcLogin:BreakGlassAccounts (e-mails, trimmed, case-insensitive).
  • IExternalSignInPolicy.PasswordSignIn(customer, SignInSurface) replaces RequiredProvider. In ProviderOnly every password is refused except break-glass accounts on the Admin panel; when the OpenID Connect login is not installed, active or configured the policy fails closed (only break-glass) and logs an error at most every five minutes. Accepted break-glass sign-ins are logged as warnings.
  • Every caller passes its surface: storefront and panel login validators, LoginCustomer, password recovery (storefront and panels), cookie validation, Frontend API login and refresh (guest tokens unaffected). Legacy API users are refused in ProviderOnly.
  • Bearer tokens obtained with a password before the switch stop working: legacy API tokens are refused, Frontend API tokens of registered customers are re-checked.
  • Passwords never expire in ProviderOnly (no account is sent to a change-password page it cannot use).
  • Browser sign-in links any existing account (staff and two-factor accounts included) by the provider-verified e-mail; an unverified e-mail is refused (OidcLoginRefusal.EmailNotVerified). Links made by e-mail are not re-checked while the mode is on; switching back to Mixed restores the earlier rules.
  • Guest checkout is treated as off in ProviderOnly (the stored setting is not changed).
  • Startup check logs an error when ProviderOnly is set without a configured, installed OpenID Connect login.

Breaking changes

IExternalSignInPolicy.RequiredProvider is replaced by PasswordSignIn(Customer, SignInSurface); ICustomerManagerService.LoginCustomer gains an optional surface parameter. Behaviour in Mixed is unchanged.

Testing

  1. dotnet test GrandNode.slnx (new tests: sign-in policy per surface and mode, break-glass list, resolver linking, startup check, guest checkout helper, password expiry, bearer token checks).
  2. With OidcLogin:SignInMode=ProviderOnly and BreakGlassAccounts=[admin e-mail]: password sign-in on the storefront and panels is refused; the break-glass account signs in on the Admin panel and a warning is logged; /api/token/create and the Frontend API password login are refused.
  3. End-to-end verified with Keycloak 26.8 and Zitadel v4.19 together with the stacked web and plugin changes.

Copilot AI balanced review requested due to automatic review settings October 14, 2026 07:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

… unknown provider user at the first sign-in, without the registration form
@KrzysztofPajak
KrzysztofPajak merged commit 5f5056c into develop Oct 14, 2026
6 checks passed
@KrzysztofPajak
KrzysztofPajak deleted the feature/oidc-provider-only-core branch October 14, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants