feat(auth): configurable OAuth client authentication for OpenID4VCI auth-code flow#4320
Merged
Merged
Conversation
* test(storage): fix flaky minimemcached nil-pointer panic The minimemcached test server spawns a goroutine that calls Accept() on its listener, while Close() nils that listener. On very short tests the cleanup's Close() could run before the goroutine entered Accept(), dereferencing a nil listener inside the dependency and crashing the test binary with a panic that no test can recover (it runs in a foreign goroutine). Block in the test helper until the server answers a probe connection, guaranteeing the accept loop is parked in Accept() before the test proceeds. Close() then unblocks it cleanly instead of racing startup. Assisted by AI * test(storage): link upstream issue for the minimemcached workaround Reference daangn/minimemcached#14 (fix in PR #13) so the workaround can be removed once an upstream release ships the fix. Assisted by AI
…uth-code flow Add experimental auth.experimental.clients config so the node can present a configured client_id (and client_secret via client_secret_post) to external authorization servers that do not understand the Nuts-specific entity_id client_id scheme. Entries are matched against the OAuth Authorization Server issuer; when no entry matches, behavior is unchanged (did:web + entity_id). Client secrets are redacted from the logged/printed configuration. Implements #4316. Assisted by AI
reinkrul
marked this pull request as ready for review
June 4, 2026 09:39
reinkrul
requested review from
gerardsn,
stevenvegt and
woutslakhorst
as code owners
June 4, 2026 09:39
reinkrul
marked this pull request as draft
June 4, 2026 09:39
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.
Implements #4316.
EXPERIMENTAL — this configuration may change or be removed without further notice (flagged in code doc comments and nested under
auth.experimental).What
Adds per-server OAuth client configuration so the node can authenticate to external authorization servers in the OpenID4VCI authorization code flow with a registered
client_id+client_secret, instead of the Nuts-specificdid:web+client_id_scheme=entity_iddefaults that third-party servers (e.g. AET/OpenIddict) reject.Env:
NUTS_AUTH_EXPERIMENTAL_CLIENTS_0_SERVERURL/_CLIENTID/_CLIENTSECRET(single-token keys round-trip through the_→.env delimiter).Behavior
authzServerMetadata.Issuer), trailing-slash-normalized — notcredential_issuer(AET splits them:.../aetvs.../aet-oauth).client_id, dropclient_id_scheme.client_id;client_secretviaclient_secret_post(TODO: derive method from AS metadata + supportclient_secret_basic). Empty secret → public client (PKCE only).did:web+entity_id). Fully additive.serverurlrequired + valid URL (HTTPS in strict mode),clientidrequired, no duplicateserverurl.clientsecretredacted from logged/printed config (wholeauth.experimental.clientssubtree, covering both YAML-slice and env-indexed key forms).Scope
Only the OpenID4VCI auth-code flow is wired; the config shape is protocol-neutral for later reuse (plain OAuth2, OpenID4VP). Not a pflag (no
[]structflag type), so it doesn't appear inserver_options.rst; documented via experimental doc comments + #4316.Tests
auth: lookup match/normalize/miss, validation cases.auth/api/iam: authorization request (configuredclient_id, no scheme) and token request (configuredclient_id+ secret) vs unchanged default path.auth/client/iam:client_secret_poston the wire; no secret for public client.core: config redaction of descendant/array keys.Verified empirically against AET: public
client_id→invalid_client;client_secret_postaccepted.🤖 Assisted by AI