Skip to content

Web API: accept identity provider tokens next to the API-user JWT (3/7) - #893

Merged
KrzysztofPajak merged 67 commits into
developfrom
feature/oidc-module-api
Oct 11, 2026
Merged

KrzysztofPajak merged 67 commits into
developfrom
feature/oidc-module-api

Conversation

@KrzysztofPajak

Copy link
Copy Markdown
Member

Type: feature

Issue

Grand.Module.Api only accepts GrandNode's own JWT. It must also accept identity-provider tokens without breaking existing integrations. Part 3 of the OIDC stack (base: PR 2).

Solution

  • OidcSchemeSelector forwards a Bearer request to the Oidc scheme when the token is the provider's (issuer equals the Authority, an asymmetric algorithm, or no readable JWT); the existing JWT keeps its scheme. A bearer value that is not a JWT is treated as no token.
  • AuthorizeApiAdminFilter refuses every scheme when BackendAPI is disabled (before, this was enforced only for the legacy JWT).
  • /api is configured as a protected resource in appsettings (off with the rest of the feature).
  • UserApi, IUserApiService and IJwtBearerAuthenticationService are marked [Obsolete]; the admin API users page shows a deprecation notice (resource in DefaultLanguage.xml and en_250.xml, 2.5 migration).

Breaking changes

None for running integrations: the legacy API-user JWT still works. Plugin code using the types above now gets obsolete warnings.

Testing

  1. dotnet test src/Tests/Grand.Module.Api.Tests and dotnet test src/Tests/Grand.Web.Common.Tests - all pass.
  2. Legacy API user token: /api/... still answers 200.
  3. Provider token, following docs/oidc-resource-server.md sections 6/7 (PR 4): right audience and scope give 200; a wrong audience or a missing scope give 401/403 with WWW-Authenticate.

… conditions, scheme always registered

The derived audience and resource_metadata URL come from the store resolved for the request, never from the Host header. Resources with account conditions are refused until those checks exist. With the resource server disabled the Oidc scheme is still registered with no issuer and no keys, so endpoints naming it answer 401. authorization_servers publishes the Authority as configured, an http Authority requires RequireHttpsMetadata=false, garbage tokens log at Information, and the startup skips an uninstalled database.
…e request through a request customer resolver
…back-office accounts; one identity per customer
…thorization server metadata cannot be obtained
OIDC link records get an identifier derived from the customer (first 12 bytes of
SHA-256 over the provider name and customer id), so the primary key rejects a
second OIDC link for the same customer on MongoDB and LiteDB. A request that
loses the race to another subject gets the linked-to-another-identity refusal
instead of a second link.
… OIDC identity per customer enforced by the link id
Base automatically changed from feature/oidc-customer-mapping to develop October 11, 2026 12:32
Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcSchemeSelector.cs Fixed
Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcSchemeSelector.cs Fixed
Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcSchemeSelector.cs Fixed

@KrzysztofPajak KrzysztofPajak left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Review of the Bearer → Oidc forwarding. Ten findings inline; 1–4 and 10 should be fixed before merge, the rest are cleanups. Fixes made here need to be propagated up the stack (#894–#897).

Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcSchemeSelector.cs
Comment thread src/Modules/Grand.Module.Api/Filters/AuthorizeApiAdminAttribute.cs Outdated
Comment thread src/Modules/Grand.Module.Api/Filters/AuthorizeApiAdminAttribute.cs
Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcSchemeSelector.cs Outdated
Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcSchemeSelector.cs Outdated
Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcSchemeSelector.cs Outdated
Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcSchemeSelector.cs Outdated
Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcRequestCustomerResolver.cs Outdated
Comment thread src/Web/Grand.Web/App_Data/appsettings.json Outdated
Copilot AI balanced review requested due to automatic review settings October 11, 2026 13:44

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.

@KrzysztofPajak

Copy link
Copy Markdown
Member Author

Review fixes:

All ten review findings are fixed on feature/oidc-module-api in eleven commits, one concern each, and merged up through #894–#897:

  • API users trust only tickets the Bearer scheme issued itself.
  • A disabled Web API withdraws /api from the registry, so tokens are refused before any customer is resolved or the store is pinned.
  • Only the Bearer scheme forwards to Oidc.
  • Routing uses the algorithm alone, checked against the Oidc scheme's own list, with one parse cached per request.
  • The work context follows the same decision.
  • The kill switch now also covers ignore: true actions.
  • Vendors and store managers are denied on /api by default.

Two points differ from the review:

  • The kill switch uses a generic IOidcDisabledPathProvider hook rather than a check on the resource name.
  • The PostConfigure_SkipsOidc_ChainsPreviousSelector test did not cover the removed Enabled branch. It was reworked, not deleted.

The three generic catches became one filtered catch over the three exception types the parser throws. The guide on #894 now covers algorithm-only routing, the earlier kill switch and the Deny defaults. Nothing is left open.

Comment thread src/Web/Grand.Web.Common/Security/Oidc/OidcProtectedResourceRegistry.cs Dismissed
@KrzysztofPajak
KrzysztofPajak merged commit 978a081 into develop Oct 11, 2026
6 checks passed
@KrzysztofPajak
KrzysztofPajak deleted the feature/oidc-module-api branch October 11, 2026 14:45
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