Skip to content

Support OpenIddict 7.0 client-assertion audience via discovery - #42

Merged
fw2568 merged 4 commits into
mainfrom
feature/openiddict7-client-assertion
May 31, 2026
Merged

Support OpenIddict 7.0 client-assertion audience via discovery#42
fw2568 merged 4 commits into
mainfrom
feature/openiddict7-client-assertion

Conversation

@fw2568

@fw2568 fw2568 commented May 29, 2026

Copy link
Copy Markdown
Member

The eryph identity server is moving to OpenIddict 7.0, which requires the issuer as the client-assertion audience and the new client-authentication+jwt token type (the old token_endpoint audience is rejected). To keep a single client library working against both old and new eryph servers, the assertion format is now negotiated from the server's discovery document.

  • ClientCredentials reads the OpenID Connect discovery document from the identity provider and detects the custom metadata flag eryph_client_assertion_audience: when present (issuer) it uses the issuer as the audience and the client-authentication+jwt type; otherwise it falls back to the token-endpoint audience (older servers). Every eryph server serves discovery, so a failure to read it surfaces as an AccessTokenException rather than silently downgrading to a format the server would reject.
  • GetClientAccessToken stays a single-request primitive and gains optional audience/tokenType parameters so the caller can pass the negotiated values.
  • Adds Microsoft.IdentityModel.Protocols.OpenIdConnect 8.2.0, matching the IdentityModel version already used in the repo (the whole Microsoft.IdentityModel.* / System.IdentityModel.Tokens.Jwt stack resolves uniformly to 8.2.0, with no advisory warnings).
  • Adds tests for the new-server, legacy-server and discovery-failure paths (both the GetClientAccessToken primitive and the ClientCredentials end-to-end path).

The private key is also pinned in unmanaged memory only briefly (around reading the RSA parameters), not across the discovery call.

Rebased onto current main (which made GetClientAccessToken take the token endpoint
explicitly and fixed the multi-scope request). The eryph server upgraded to OpenIddict
7.0 requires the issuer as the client-assertion audience and the client-authentication+jwt
token type; older servers expect the token endpoint audience.

ClientCredentials now reads the discovery document from the identity provider and detects
the custom metadata flag eryph_client_assertion_audience to choose the format, then passes
the resolved audience/token type to the GetClientAccessToken primitive (which gains optional
audience/tokenType parameters and stays a single request). Every eryph server serves the
discovery document, so a failure to read it surfaces as an AccessTokenException rather than
silently downgrading to a format the server would reject.
@fw2568
fw2568 force-pushed the feature/openiddict7-client-assertion branch from 340afa1 to 9c7050b Compare May 29, 2026 14:20
Fetch the discovery document before pinning the private key in unmanaged memory,
and unpin it immediately after reading the RSA parameters, so the plaintext key is
exposed for as short a time as possible (no longer held across the discovery call).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates client-credential token acquisition to support eryph identity servers using OpenIddict 7.0 discovery metadata while preserving legacy token assertion behavior.

Changes:

  • Adds discovery-document parsing to choose client-assertion audience and JWT typ.
  • Extends token request generation to accept custom audience/token type.
  • Adds tests for new-server, legacy-server, and discovery-failure paths.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Eryph.IdentityModel.Clients/ClientCredentials.cs Resolves assertion format from discovery metadata before requesting tokens.
src/Eryph.IdentityModel.Clients/Eryph.IdentityModel.Clients.csproj Adds OpenID Connect protocol metadata parsing dependency.
src/Eryph.IdentityModel/Clients/HttpClientRequestExtensions.cs Allows token requests to override assertion audience and JWT header type.
test/Eryph.IdentityModel.Clients.Tests/ClientCredentialsTests.cs Adds coverage for discovery-driven assertion behavior.
test/Eryph.IdentityModel.Tests/HttpClientExtensionsTests.cs Adds direct assertion-generation tests for audience and token type.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Eryph.IdentityModel.Clients/Eryph.IdentityModel.Clients.csproj

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread src/Eryph.IdentityModel/Clients/HttpClientRequestExtensions.cs Outdated
…ibility

Adding the audience/tokenType parameters as optionals changed the public method's
CLR signature, which would break callers compiled against the previous package
version (MissingMethodException) when only the package is upgraded. Keep the
original 5-parameter overload and have it delegate to the new 7-parameter overload.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment on lines +125 to +132
var usesIssuerAudience =
configuration.AdditionalData.TryGetValue(ClientAssertionAudienceMetadata, out var value)
&& string.Equals(value?.ToString(), ClientAssertionAudienceIssuer, StringComparison.OrdinalIgnoreCase)
&& !string.IsNullOrEmpty(configuration.Issuer);

return usesIssuerAudience
? (configuration.Issuer, ClientAuthenticationJwtType)
: (_tokenUrl.AbsoluteUri, null);
If the discovery document advertises eryph_client_assertion_audience=issuer but
contains no issuer, the metadata is invalid: throw instead of downgrading to a
legacy token-endpoint assertion the server would reject. Add a test.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

fw2568 added a commit to eryph-org/dotnet-clientruntime that referenced this pull request May 30, 2026
…Clients

Bump Eryph.IdentityModel.Clients to the preview build that negotiates the
client-assertion audience via discovery (eryph-org/dotnet-identitymodel#42), so
the new auth flows through ClientRuntime for end-to-end testing against an
OpenIddict 7 eryph server. Pinned to the PR preview on the dbosoft feed; to be
re-pinned to the released version once dotnet-identitymodel#42 merges.
@fw2568
fw2568 merged commit 3ffe8ab into main May 31, 2026
6 checks passed
fw2568 added a commit to eryph-org/dotnet-clientruntime that referenced this pull request May 31, 2026
…ients) (#66)

* Consume OpenIddict 7 client-assertion preview of Eryph.IdentityModel.Clients

Bump Eryph.IdentityModel.Clients to the preview build that negotiates the
client-assertion audience via discovery (eryph-org/dotnet-identitymodel#42), so
the new auth flows through ClientRuntime for end-to-end testing against an
OpenIddict 7 eryph server. Pinned to the PR preview on the dbosoft feed; to be
re-pinned to the released version once dotnet-identitymodel#42 merges.

* Use released Eryph.IdentityModel.Clients 0.7.0
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