Align OpenIddict with Duende IdentityServer - #2549
Closed
pieroviano wants to merge 122 commits into
Closed
pieroviano wants to merge 122 commits into
pieroviano wants to merge 122 commits into
Conversation
…r and client stacks Server: opt-in request object support (EnableRequestObjectSupport) for the authorization and pushed authorization endpoints, request objects validated using the client JSON Web Key Set (optionally encrypted), RFC 9101 merge semantics, global and per-client requirements (RequireSignedRequestObjects, ft:jar) and discovery metadata. Client: request objects sent when required by the server or enabled in the registration (UseSignedRequestObjects), signed with the registration's asymmetric key.
…mode) to the server stack - New backchannel authentication endpoint (SetBackchannelAuthenticationEndpointUris, AllowClientInitiatedBackchannelAuthenticationFlow, ASP.NET Core/OWIN pass-through). - auth_req_id issued as an inactive reference token, redeemed with the urn:openid:params:grant-type:ciba grant (authorization_pending, access_denied, expired_token). - OpenIddictServerService to list, approve and reject pending requests. - Generic polling interval (interval parameter + slow_down) for the device code and CIBA grants. - Discovery metadata and configuration validation.
…ient stack - OpenIddictClientService.ChallengeUsingBackchannelAsync/AuthenticateWithBackchannelAsync. - Backchannel authentication request pipeline (client authentication negotiation, client assertions, mTLS certificates, System.Net.Http integration, response validation). - CIBA grant support at the token endpoint (auth_req_id, identity token required). - Discovery extraction of the backchannel authentication metadata. - Only enforce the pushed authorization requests requirement for interactive flows.
- New Key entity: IOpenIddictKeyStore/IOpenIddictKeyManager, EF Core, EF6 and MongoDB stores. - OpenIddictServerKeyRing creates, announces, rotates and retires RSA keys; credentials are resolved per transaction. - IOpenIddictServerKeyProtector, with an ASP.NET Core Data Protection implementation. - Local validation follows key rotation; opt-in Quartz key pruning.
- Validate DPoP proofs at the token, PAR and userinfo endpoints (typ, alg, public jwk, htm/htu, iat, ath) - Replay protection via redeemed token entries when token storage is enabled - Optional server nonces (use_dpop_nonce + DPoP-Nonce header) - Bind access tokens and public-client refresh tokens with cnf.jkt; token_type=DPoP - dpop_jkt at authorization/PAR, enforced at code redemption - Global RequireDPoP option, per-client ft:dpop requirement, discovery metadata - DPoP scheme and WWW-Authenticate algs in ASP.NET Core and OWIN hosts
- Accept access tokens sent using the DPoP scheme (ASP.NET Core and OWIN hosts) - Validate DPoP proofs (htm/htu/iat/ath, public jwk) and cnf.jkt binding for local and introspected tokens - Reject DPoP-bound tokens sent as bearer tokens and unbound tokens sent with the DPoP scheme - Replay protection via IDistributedCache when registered - WWW-Authenticate DPoP challenges with algs
- EnableDPoPTokenBinding(); per-registration DPoPSigningCredentials (ephemeral P-256 by default) - Negotiate DPoP from dpop_signing_alg_values_supported; send proofs to token, PAR and userinfo (DPoP scheme + ath) - Retry once on use_dpop_nonce and cache server nonces per authority - OpenIddictClientService.CreateDPoPProofAsync/GetDPoPJsonWebKeyThumbprint for resource calls - System.Net.Http handlers attach DPoP header and extract DPoP-Nonce
- Progress row, commits and deviations - Gap matrix, implemented phases, test counts and remaining work
- Validate proof signatures using a minimal JWK (kty/crv/x/y or kty/e/n) so x5c can't substitute the verification key - Reject algorithms incompatible with the key type or curve - Add helper tests for key substitution, curve mismatch, symmetric keys and invalid iat
- Certificate-based binding takes precedence at the token endpoint, so a DPoP-bound code could not be redeemed - Add client test covering both cases
- Deviations: PAR/mTLS code binding rule, assertion reuse on nonce retry, proof key hardening - Client test count
- EnableJsonWebTokenIntrospectionResponses(): signed token-introspection+jwt (iss, aud, iat, token_introspection) - Optional RSA-OAEP/A256CBC-HS512 encryption with the client's JWKS enc key (non-degraded mode) - ASP.NET Core/OWIN: Accept header detection and application/token-introspection+jwt responses - Discovery: introspection_signing/encryption alg metadata - Integration tests
- OpenIddictClientRegistration.RequireJsonWebTokenIntrospectionResponses - System.Net.Http: Accept header and token extraction - ValidateIntrospectionResponseToken: typ/iss/signature/aud checks, optional decryption, token_introspection extraction - Unit tests
- RequireJsonWebTokenIntrospectionResponses() option (introspection mode) - System.Net.Http: Accept header and token extraction - ValidateIntrospectionResponseToken: typ/iss/signature/aud checks, optional decryption, token_introspection extraction - Unit tests
- RFC 9701 requires an authenticated caller; public clients get plain JSON - Integration test
- Encrypt only when the application sets intr_rsp:enc_alg (RSA-OAEP), as RFC 9701 section 6 requires - Support intr_rsp:enc_enc (A128CBC-HS256 by default, or A256CBC-HS512) and publish both in discovery - Throw (ID0552/ID0553) on unsupported settings or a missing RSA enc key instead of sending plaintext - Trim whitespace around JWT introspection response bodies in the client and validation stacks - Add tests for opt-in, defaults, bad settings, tokens signed with local keys and unsigned JWEs
- Encryption deviation now describes the intr_rsp:enc_alg / intr_rsp:enc_enc opt-in - List the review fixes commit
- Add IOpenIddictClientRegistrationProvider (static options provider registered by default, AddRegistrationProvider) - Extract registration initialization/validation from OpenIddictClientConfiguration - OpenIddictClientService resolves static and dynamic registrations; dynamic ones are validated (declared redirect URIs, no static id collision) and cached by id (DynamicRegistrationCacheLifetime) - Handlers default to the unique registration through the service - ASP.NET Core: decorate IAuthenticationSchemeProvider to resolve dynamic provider names as forwarded schemes - OWIN: resolve dynamic provider names for forwarded challenges, sign-outs and authentication - WebIntegration: make ConfigureProvider/ValidateProvider browsable for dynamic registrations
- Client: provider resolution, initialization, validation, caching and handler fallbacks - ASP.NET Core/OWIN: dynamic provider names as forwarded schemes/types, challenge and callback
- Progress row and deviations table - Gap matrix, implemented phases and remaining work updated
- Reuse a cached dynamic registration only if issuer, provider name and client id are unchanged - Check the cache before creating configuration managers/DPoP keys - Purge expired cache entries on insert - Tests for changed and unchanged cached registrations; plan updated
- Cookie OnValidatePrincipal access token refresh (keyed single-flight, result retention, invalid_grant sign-out) - User/client access token DelegatingHandler and YARP transform (DPoP-aware) - MapOpenIddictBffEndpoints: login, logout (sid check), user (X-CSRF), callbacks, back-channel logout - Back-channel logout token validation + IOpenIddictClientAspNetCoreBffSessionStore / in-memory store - Store backchannel_access_token_type in ASP.NET Core and OWIN client hosts - Tests for refresh, CSRF, endpoints, logout, handlers and proxy
Map the SOAP artifact resolution endpoint in the ASP.NET Core and OWIN hosts, redirect with SAMLart for HTTP-Artifact assertion consumer services and consume request states before returning a response.
- Enable request replay protection by default and add DisableRequestReplayProtection() - Consume request states only once the response was created and stored - Encrypt stored artifact messages with a key derived from the artifact handle - Size-limit the private in-memory replay cache and artifact store - Reject AuthnRequests combining AssertionConsumerServiceIndex and ProtocolBinding - Expose ArtifactResolutionResult.ErrorDescription and cover rejection paths in tests
- Reject messages whose replay entry cannot be stored (full private cache or discarding distributed cache) - Never evict private in-memory replay entries before they expire - Use per-key striped locks in the replay cache and artifact store - Bind legacy (version 2) request states to a single use instead of rejecting them - Accept AssertionConsumerServiceIndex with a ProtocolBinding matching the indexed endpoint - Remove the redundant EnableRequestReplayProtection() builder method
- shared/OpenIddict.Extensions/Saml/OpenIddictSamlHelpers.cs: encoding, secure XML loading, RSA-SHA2 redirect/enveloped signatures (element-level, nested-signature safe), auto-post page - OpenIddict.Server.Saml keeps only IdP-specific wrappers (redirect query parsing, single-root-signature rule)
… and decryptor - Resources ID0880-ID0907, ID2440-ID2459, ID6680-ID6684
…n and metadata services - Resources ID0908-ID0909
… provider - Round trips (both bindings), signed/unsigned combinations, wrapping, DTD, InResponseTo/relay state/expiry, clock skew, audience, destination, recipient, replay, error status, encrypted assertions, metadata import (HTTPS/file/signed), dynamic registrations and caching
- Authentication handler: challenges (HTTP-Redirect/HTTP-POST), assertion consumer service (sign-in or pass-through), metadata endpoint - Protected request state in SameSite=None correlation cookies keyed by a random relay state - Scheme provider decorator exposing static and dynamic registration provider names as forwarded schemes - Resources ID0910-ID0911; TestServer tests against the OpenIddict SAML identity provider
…on and response validation - Cache all registration lookups (including negative results) with a bounded cache; fresh provider results replace cached registrations; add ClearCache - Reject UNC and dynamic file metadata addresses; add AllowedDynamicMetadataHosts - Honor metadata validUntil/cacheDuration and never fall back to expired metadata - Require HTTPS single sign-on endpoints unless AllowInsecureIdentityProviderEndpoints - Reject disabled request signing when AuthnRequestsSigned is advertised - Ignore bearer confirmations containing NotBefore; keep IdP status text out of error descriptions
…ponses - ASP.NET Core scheme provider uses the cached SAML registration lookups - OWIN challenges ignore provider names owned by other authentication middleware, use cached lookups and are skipped when headers were already sent - Send X-Content-Type-Options: nosniff with ACS error responses
- OpenIddictServerAspNetCoreAdminOperations: describe entries, filtered paging, cascading authorization revocation, key revocation with key ring invalidation, public JWKS writer - Admin API endpoints use the shared operations (behaviour unchanged)
- MapOpenIddictAdminUI(policy, prefix) + AddOpenIddictAdminUI(options): static SSR Razor components over the untyped managers - Applications (search, paging, create, edit, secret set/generate/remove, delete), scopes CRUD, authorizations and tokens (filters, details, revoke), keys (list, revoke) - Shared admin operations reused; stored secrets, token payloads and key material never rendered; private JWK parameters stripped - Antiforgery validated on every post, security headers (CSP, no-store, DENY), embedded stylesheet - Resource strings ID0680-ID0683, ID2340-ID2343, ID6480-ID6484 - TestServer tests: policy enforcement, antiforgery, create/edit/secret/delete, scopes, authorization/token/key revocation
- Optional AdminUI parameter (dotnet new --admin-ui) referencing OpenIddict.Server.AspNetCore.AdminUI and mapping it under /admin with the admin policy
- Treat identifiers the store can't convert (e.g. GUID keys) as unknown entities instead of failing the request - Bound the in-memory application search and always surface an exact client_id match - Detect endpoints that make the admin UI routes ambiguous (e.g. the admin API mapped with the same prefix) - Indicate when an authorization has more tokens than displayed - Hide the Razor page components from IntelliSense (not a supported API surface) - Add tests for secret generation, JWKS replacement/removal, key ring invalidation and real EF Core stores
…pplications - Render the original redirect URI strings so saving the form keeps exact-match registrations intact - Keep stored application, client and consent types not known by the admin UI - Filter the token list by authorization and link to it from the authorization details
Track SAML service provider sessions as server-side sessions sharing the login identifier, validate signed LogoutRequest/LogoutResponse messages (HTTP-Redirect and HTTP-POST), propagate logouts to the session participants (front-channel redirect chain, SOAP back-channel, OpenID Connect end session integration), publish SingleLogoutService metadata and add the single logout endpoint to the ASP.NET Core and OWIN hosts.
…ipant failures and NameID matching
…e actual session status after admin UI termination failures
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Duende IdentityServer parity
This PR adds the remaining Duende IdentityServer parity features to the OpenIddict fork. New features are opt-in, except the default-behaviour changes listed below.
Features
sidin tokens, sliding and absolute expiration, revocation that cascades to tokens and authorizations, session queries by subject, client orsid, admin API list/get/terminatelogout_tokensent through a pluggable sender), Front-Channel Logout 1.0 (iframe URL helpers), Session Management 1.0 (check_session_iframe,session_state)logout_tokenvalidation shared with the BFF,session_stateandcheck_session_iframeexposed to appsRegisterAsyncand management helpersOpenIddict.Server.SystemNetHttpnotification senderjwt,query.jwt,fragment.jwtandform_post.jwtresponse modes, signing and optional encryption, discovery metadata, client-side validationrequest_uri, with SSRF protections and a per-client allow-listOpenIddict.Client.Samlpackage with.AspNetCoreand.Owinhosts, dynamic SAML providers, SAML signature helpers shared with the IdPOpenIddict.Server.AspNetCore.AdminUIBlazor library (applications, scopes, authorizations, tokens, keys, sessions),--admin-uitemplate switchBehaviour changes
IDistributedCache.WantAuthnRequestsSignedto true.OpenIddictServerSamlServiceconstructor has two more parameters.frontchannel_logout_urimust share an origin with a registered redirect URI.exp(can be turned off).iatis only accepted within clock skew.client_notification_tokenmust follow the b64token syntax.transaction_failedis no longer mapped toserver_error.Authorizationheader.WWW-Authenticateheaders.ReferenceIduniqueness inside a serializable transaction.openiddict_.OpenIddict.Server.SystemNetHttpdoes not depend on Polly.Tests
templates/verify.shpassed: 4 template builds and 18 smoke checks.OpenIddict.Sandbox.Maui.Client, which needs themaui-tizenworkload.Known gaps
expired_tokenpush.jwks_uri,client_secret_jwt, or initial access tokens from external issuers.8e01c78c…966d50ebdon't compile on their own; only the final state builds.Security notes
IDistributedCachearen't atomic across instances.client_credentialscan be registered by default.FrontchannelLogoutSessionRequired=falseallows logout CSRF.EnableIdentityTokenHintSessionResolutionon, a leaked ID token can end a session.