Skip to content

DO NOT MERGE: Project branch for Generic Functions (Pilot Phase)#4308

Draft
reinkrul wants to merge 123 commits into
masterfrom
project-gf-pilot
Draft

DO NOT MERGE: Project branch for Generic Functions (Pilot Phase)#4308
reinkrul wants to merge 123 commits into
masterfrom
project-gf-pilot

Conversation

@reinkrul

@reinkrul reinkrul commented Jun 2, 2026

Copy link
Copy Markdown
Member

Pilot Phase branch for Generic Functions, branched from project-gf with master merged in. Kept separate from project-gf so the PoC branch's backwards compatibility stays untouched.

Changes vs project-gf

Feature work added on top of project-gf that is not yet on master. Each item has its own PR open against master; merge order there is independent of this branch.

Change Master PR Notes
Configurable OAuth client authentication for the OpenID4VCI auth-code flow #4327 Already merged into this branch via #4320
http.client.log — log outgoing HTTP requests #4337
Configurable OpenID4VCI request profiles with built-in AET profile #4340 Pilot additionally aligns the AET profile scope to DefaultConfig (temporary scope hardcode added then removed); not yet reflected in #4340
Metadata discovery: support both insert (RFC 8414) and append (OIDC) well-known locations, tolerate trailing-slash in the identifier match #4346 Implements #4310
Remove non-conformant Display from issuer metadata #4347

Reverted (net no change vs project-gf)

Branch infrastructure (pilot-only)

  • CI builds Docker images for the project-gf-pilot branch.

Merge resolution notes

Both project-gf and master independently implemented an RFC 7523 jwt-bearer flow; resolved as follows:

  • jwt-bearer flow — adopted master's design: two-VP flow gated by service_provider_subject_id + auth.experimental.jwtbearerclient. Dropped project-gf's single-VP grant negotiation.
  • Grant-type constant — consolidated to oauth.JwtBearerGrantType.
  • policy_id — dropped (request param, client signature, and OpenAPI field); the presentation definition is resolved from scope. API regenerated.
  • Preserved project-gf behavior — disabled access-token cache (credential-revocation testing), OpenIdCredentialIssuerMetadata / VerifiableCredentials client methods, server-side jwt-bearer handler, GrantTypes config, gorm pinned at v1.30.2.
  • Regenerated mocks and IAM API; go mod tidy reconciled dependencies.

Full test suite passes.

Assisted by AI

stevenvegt and others added 11 commits April 22, 2026 15:08
When using mCSD for addressing, the OAuth token endpoint must be
provided to the AT-Request instead of being resolved via a DID-Document.
This commit adds a request param for this.
…l Request

Adds an optional credential_details JSON object to POST /internal/auth/v2/{subjectID}/request-credential.
The node uses it as the base body of the outgoing OpenID4VCI Credential Request and overlays its own
JWT proof on top. Lets the wallet integrate with issuers (e.g. AET SDK) that accept additional fields
in the Credential Request body beyond what OpenID4VCI v1.0 defines.

Closes #4233

Assisted by AI
Switch VerifiableCredentials to TestResponseCodeWithLog so the upstream
response body is surfaced in the logs, making it possible to diagnose
4xx/5xx responses from the credential endpoint.

Assisted by AI
The 1.0 spec wraps credentials in a "credentials" array; pre-1.0 drafts
returned a single "credential" string. Custom UnmarshalJSON on
CredentialResponse handles both, taking the first entry from the array
form and warning if the issuer returned more.

Assisted by AI
; Conflicts:
;	auth/api/iam/bearer_token.go
;	auth/api/iam/s2s_vptoken_test.go
;	auth/auth.go
;	auth/client/iam/client.go
;	auth/client/iam/openid4vp.go
;	auth/client/iam/openid4vp_test.go
;	auth/services/oauth/authz_server_test.go
;	auth/test.go
;	crypto/jwx/algorithm.go
;	crypto/jwx_test.go
; Conflicts:
;	auth/api/iam/openid4vci.go
;	auth/api/iam/openid4vci_test.go
;	auth/api/iam/session.go
;	auth/client/iam/client.go
;	docs/_static/auth/v2.yaml
;	docs/pages/release_notes.rst
When the OpenID4VCI credential endpoint returns a non-2xx status, log the
status code and response body (Warn) so issuance failures (e.g. 400) can be
diagnosed without enabling debug. The body is already buffered for
structured-error parsing, so no extra read.

Assisted by AI
Pilot branch carrying the master merge so project-gf stays untouched.

Conflict resolution (overlapping RFC 7523 jwt-bearer work on both sides):
- jwt-bearer flow: adopted master's design (two-VP flow gated by
  service_provider_subject_id + auth.experimental.jwtbearerclient).
  Dropped project-gf's single-VP grant negotiation.
- Consolidated grant-type constant to oauth.JwtBearerGrantType.
- Dropped policy_id (request param, client signature, OpenAPI field);
  the presentation definition is resolved from scope. Regenerated API.
- Preserved project-gf-only behavior: disabled access-token cache
  (credential-revocation testing), OpenIdCredentialIssuerMetadata /
  VerifiableCredentials client methods, server-side jwt-bearer handler,
  GrantTypes config, gorm pinned at v1.30.2.
- Regenerated mocks and IAM API after resolving.

Assisted by AI
@qltysh

qltysh Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Qlty


Coverage Impact

⬇️ Merging this pull request will decrease total coverage on master by 0.55%.

Modified Files with Diff Coverage (35)

RatingFile% DiffUncovered Line #s
Coverage rating: C Coverage rating: C
auth/auth.go85.3%206-260
Coverage rating: A Coverage rating: A
auth/config.go100.0%
Coverage rating: A Coverage rating: B
core/tls.go0.0%76-80
Coverage rating: A Coverage rating: A
auth/cmd/cmd.go100.0%
Coverage rating: A Coverage rating: A
auth/api/iam/metadata.go100.0%
Coverage rating: B Coverage rating: B
auth/oauth/types.go0.0%236-238
Coverage rating: C Coverage rating: C
core/server_config.go100.0%
Coverage rating: B Coverage rating: B
auth/api/iam/api.go74.5%240-249, 788-789
Coverage rating: A Coverage rating: B
auth/api/auth/v1/api.go95.0%280
Coverage rating: B Coverage rating: B
auth/api/iam/openid4vp.go75.9%391, 735-736...
Coverage rating: C Coverage rating: C
auth/client/iam/openid4vp.go100.0%
Coverage rating: C Coverage rating: C
auth/services/oauth/relying_party.go100.0%
Coverage rating: B Coverage rating: B
auth/api/iam/access_token.go86.4%77-79
Coverage rating: A Coverage rating: A
auth/api/iam/openid4vci.go100.0%
Coverage rating: C Coverage rating: C
auth/openid4vci/client.go100.0%
Coverage rating: B Coverage rating: C
auth/client/iam/client.go71.3%242-243, 246-247...
Coverage rating: B Coverage rating: B
auth/api/iam/validation.go78.3%47-48, 51-52, 57-59...
New Coverage rating: D
auth/api/iam/types.go61.9%93-94, 97-98...
New Coverage rating: F
auth/oauth/tracing.go0.0%52-73
New Coverage rating: B
auth/api/iam/bearer_token.go93.1%83-84
Coverage rating: B Coverage rating: B
http/engine.go100.0%
Coverage rating: A Coverage rating: A
http/cmd/cmd.go100.0%
Coverage rating: B Coverage rating: B
vcr/cmd/cmd.go0.0%44-45
Coverage rating: A Coverage rating: A
http/config.go100.0%
Coverage rating: B Coverage rating: B
http/client/client.go66.7%93-94
New Coverage rating: A
http/clientlogger.go90.2%51-52, 76-77
Coverage rating: C Coverage rating: C
vcr/vcr.go100.0%
Coverage rating: B Coverage rating: B
vcr/holder/sql_wallet.go100.0%
Coverage rating: A Coverage rating: B
vcr/credential/util.go0.0%122-132
Coverage rating: A Coverage rating: A
vcr/revocation/types.go100.0%
Coverage rating: B Coverage rating: B
vcr/holder/presenter.go60.0%132-133, 139-140...
Coverage rating: A Coverage rating: A
vcr/verifier/verifier.go33.3%157-158
Coverage rating: A Coverage rating: B
vcr/credential/resolver.go0.0%47-51
Coverage rating: A Coverage rating: B
vcr/revocation/statuslist2021_verifier.go100.0%
New Coverage rating: F
vcr/credential/dezi.go44.1%24-26, 75-76, 80-81...
Total63.8%
🤖 Increase coverage with AI coding...
In the `project-gf-pilot` branch, add test coverage for this new code:

- `auth/api/auth/v1/api.go` -- Line 280
- `auth/api/iam/access_token.go` -- Line 77-79
- `auth/api/iam/api.go` -- Lines 240-249 and 788-789
- `auth/api/iam/bearer_token.go` -- Line 83-84
- `auth/api/iam/openid4vp.go` -- Lines 391, 735-736, 739-740, and 742-743
- `auth/api/iam/types.go` -- Lines 93-94, 97-98, 100-101, and 111-112
- `auth/api/iam/validation.go` -- Lines 47-48, 51-52, 57-59, and 81-83
- `auth/auth.go` -- Line 206-260
- `auth/client/iam/client.go` -- Lines 242-243, 246-247, 257-269, 351-352, 382-383, 394-395, 402-403, and 407-408
- `auth/oauth/tracing.go` -- Line 52-73
- `auth/oauth/types.go` -- Line 236-238
- `core/tls.go` -- Line 76-80
- `http/client/client.go` -- Line 93-94
- `http/clientlogger.go` -- Lines 51-52 and 76-77
- `vcr/cmd/cmd.go` -- Line 44-45
- `vcr/credential/dezi.go` -- Lines 24-26, 75-76, 80-81, 86-87, 90-91, 122-248, 262-263, 301-302, 304-305, 309-310, 326-327, 329-330, 336-337, 340-341, 355, 364-367, 376-377, 384-385, 388-389, 393-394, 397-398, 401-402, and 425-486
- `vcr/credential/resolver.go` -- Line 47-51
- `vcr/credential/util.go` -- Line 122-132
- `vcr/holder/presenter.go` -- Lines 132-133, 139-140, 147-148, and 152-153
- `vcr/verifier/verifier.go` -- Line 157-158

🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

reinkrul added 6 commits June 3, 2026 06:46
Add project-gf-pilot to the build-images push/pull_request triggers so it
builds and pushes a branch-tagged image, same as project-gf.

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
Configurable OAuth client authentication for the OpenID4VCI authorization code flow (#4316).

Assisted by AI

; Conflicts:
;	auth/auth.go
Allows callers to merge issuer-specific query parameters (e.g. auth_method=SmartCard)
into the OpenID4VCI authorization request, mirroring the credential_request_params
escape hatch. Caller-supplied values override node defaults for the same key.

Assisted by AI
…params

Align the OpenID4VCI requestCredential field name with the sibling credential_request_params.
See #4328.

Assisted by AI
Adds a configurable log level for outgoing HTTP requests/responses made
by the node, mirroring http.log for incoming traffic. Reuses the existing
http.LogLevel enum (nothing/metadata/metadata-and-body) and defaults to
nothing. Wired up in http.configureClient() via a transport-wrapping hook
on the http client package.

Assisted by AI
Comment thread http/clientlogger.go Fixed
reinkrul added 11 commits June 8, 2026 12:48
Caller-supplied authorization_request_params may only add parameters to the OpenID4VCI
authorization request; attempting to override a parameter the node sets (client_id, state,
code_challenge, etc.) now fails loud with a 400 instead of silently winning.

Assisted by AI

; Conflicts:
;	auth/api/iam/openid4vci.go
The logging transport wrapper was decided when the HTTP client was
created. Engines that build their clients before the HTTP engine is
configured (e.g. auth's OpenID4VCI client) never got the wrapper, since
client.RequestLogger was still nil at construction. The HTTP engine is
registered/configured last, so http.client.log had no effect on those
clients.

Always install a thin loggingTransport indirection in getTransport that
reads RequestLogger per request, mirroring how StrictMode is read at
request time. Clients created before logging is configured now log.

Assisted by AI
Make the log level the single control instead of also depending on the
global debug verbosity:

- Log request and response headers at both 'metadata' and
  'metadata-and-body' (previously headers required debug verbosity).
- Mask credential-bearing request headers (Authorization,
  Proxy-Authorization) so they don't leak into the logs. Response
  WWW-Authenticate is a challenge, not a credential, so it is not masked.

Assisted by AI
Relocate the outgoing-request logger from the http package to http/client,
where the rest of the client transport code lives, and address naming:

- The round tripper is now loggingTransport (it logs both request and
  response), gated by client.LogRequests / client.LogRequestBodies which
  are read at request time. This replaces the clientRequestLogger type and
  the RequestLogger func indirection.
- Extract the loggable-content-types list to http/log.IsLoggableContentType
  as the single source of truth, used by both the client logger and the
  server-side body logger (previously duplicated).

Assisted by AI
…T profile

Add auth.experimental.profile.<name>.authrequest: named bundles of authorization request
parameters. A new 'profile' field on requestCredential selects one by name; the node ships a
built-in 'aet' profile (AET UZI smartcard issuer) and operator config of the same name is merged
over it. Profiles are trusted config and may override node parameters; the raw
authorization_request_params escape hatch still may not.

Implements #4338.

Assisted by AI
TEMPORARY test hack for project-gf-pilot so AET issuance can be exercised without wiring a
request profile into the caller. To be reverted once the profile mechanism is wired up. See #4338.

Assisted by AI
…faultConfig

Revert the temporary hardcoded AET scope on the OpenID4VCI authorization request (issuance now
relies on the request profile). Move the built-in 'aet' profile from a separate builtinProfiles
var into DefaultConfig and simplify AuthorizationRequestProfile to a plain lookup, matching the
master-targeting implementation (#4338 / #4340).

Assisted by AI
Metadata discovery derived URLs using only the RFC 8414 insert convention
(well-known segment at the authority root, issuer/AS path appended). Servers
that publish metadata only under the OIDC Discovery append convention
(well-known after the path) returned 404 and could not complete issuance or
token flows without per-deployment nginx rewrites.

Discovery now tries candidate locations in priority order and takes the first
matching document:
  1. insert (RFC 8414, unchanged happy path)
  2. append (OIDC Discovery)
  3. append openid-configuration (AS metadata only)

When the identifier has no path both forms collapse to one URL, so
spec-compliant servers still make a single request. Each candidate shares the
identifier's host and is SSRF-validated via core.ParsePublicURL, and the
existing identifier-match check (credential_issuer / issuer must equal the
requested identifier) is enforced on the accepted document, so the fallback
cannot be steered to an attacker-chosen file. On exhaustion the error names the
identifier and reports only non-404 failures; a >= 500 failure still maps to
502 Bad Gateway.

Assisted by AI
Some authorization servers (e.g. IdentityServer) normalize the metadata
issuer with a trailing slash, so a server reached at the append location with
issuer "https://host/oauth/" was rejected against the requested identifier
"https://host/oauth". Discovery then fell back to the credential issuer and
surfaced an unrelated 404.

Compare issuer / credential_issuer with a trailing-slash tolerance via
oauth.IdentifiersMatch. Still rejects genuinely different identifiers, so the
fallback cannot be steered to another document.

Assisted by AI
The `display` field on OpenIDCredentialIssuerMetadata was not conform
the OpenID4VCI spec (section 12.2.4). Its values were never consumed and
it caused issues with the AET integration. Since nothing reads it,
removal is safe.

Assisted by AI
…uestCredential API

Reverts the authorization_request_params feature (added/renamed/fixed in 2fcdc6a,
f337c2c, 3d205a3) on project-gf-pilot, mirroring the revert of #4333 on master. The
request-profile mechanism stays and covers the AET auth_method=SmartCard use case.

Assisted by AI
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.

4 participants