Repository navigation
Add credential_selection to access token request API #4090
Description
Parent PRD
#4067 (see PRD comment)
What to build
Add credential_query as an optional field on the ServiceAccessTokenRequest and wire it through the full access token request flow.
Call stack
The credential_query flows through the following layers:
API handler: RequestServiceAccessToken (auth/api/iam/api.go)
extracts credential_query from request body
→ RequestRFC021AccessToken (auth/client/iam/openid4vp.go)
accepts credentialQueries as new parameter
→ wallet.BuildSubmission (vcr/holder/interface.go)
accepts credentialQueries as new parameter alongside presentationDefinition
→ presenter.buildSubmission (vcr/holder/presenter.go)
if credentialQueries provided:
selector, _ = pe.NewDCQLSelector(credentialQueries, pd, pe.FirstMatchSelector)
builder.SetCredentialSelector(selector)
→ builder.Build(format)
Changes per layer
OpenAPI spec (docs/_static/auth/v2.yaml): add credential_query (optional array of DCQL credential query objects) to ServiceAccessTokenRequest.
Generated types (auth/api/iam/generated.go): regenerate to include new field.
API handler (auth/api/iam/api.go): extract credential_query from request.Body, pass to RequestRFC021AccessToken.
Client interface (auth/client/iam/interface.go): add credentialQueries []dcql.CredentialQuery parameter to RequestRFC021AccessToken.
RFC021 client (auth/client/iam/openid4vp.go): accept credentialQueries, pass to wallet.BuildSubmission.
Wallet interface (vcr/holder/interface.go): add credentialQueries []dcql.CredentialQuery parameter to BuildSubmission, placed alongside presentationDefinition since they work together — the PD defines what's required, the queries narrow which specific credentials to use.
BuildSubmission(ctx context.Context, walletDIDs []did.DID,
additionalCredentials map[did.DID][]vc.VerifiableCredential,
presentationDefinition pe.PresentationDefinition,
credentialQueries []dcql.CredentialQuery,
params BuildParams,
) (*vc.VerifiablePresentation, *pe.PresentationSubmission, error)SQL wallet (vcr/holder/sql_wallet.go): pass credentialQueries through to presenter.
Presenter (vcr/holder/presenter.go): if credentialQueries is non-empty, create a DCQL selector via pe.NewDCQLSelector(credentialQueries, pd, pe.FirstMatchSelector) and call builder.SetCredentialSelector(selector).
Design decisions
credential_queryis a function parameter onBuildSubmission(not inBuildParams) because it's about which credentials to select, not about how to build the VP.BuildParamscontains VP construction parameters (audience, format, nonce, expiry).- The DCQL selector is constructed in the presenter layer, keeping PE/DCQL concerns out of the API and client layers.
- Coexistence: existing
credentialsarray (self-attested VCs) continues to work alongsidecredential_query. - No
match_policyparameter — the DCQL filter must narrow to exactly one credential per input descriptor. See decision comment.
Example request
{
"scope": "medicatieoverdracht-gf",
"authorization_server": "https://verifier.example.com",
"credential_query": [
{
"id": "id_patient_enrollment",
"claims": [
{
"path": ["credentialSubject", "hasEnrollment", "patient", "identifier", "value"],
"values": ["123456789"]
}
]
}
]
}Acceptance criteria
-
credential_queryfield added toServiceAccessTokenRequestin OpenAPI spec (optional array) - Generated types include new field
-
RequestServiceAccessTokenhandler extracts and passescredential_querythrough the flow -
RequestRFC021AccessTokenacceptscredentialQueriesparameter -
Wallet.BuildSubmissionacceptscredentialQueriesparameter alongsidepresentationDefinition - Presenter creates DCQL selector when
credentialQueriesis non-empty - Existing
credentials(self-attested) array works alongsidecredential_query - Request without
credential_querybehaves identically to current behavior - Mocks and test call sites updated for new interface signatures
- End-to-end test: API call with
credential_queryselects correct credential from wallet - End-to-end test: API call with
credential_querymatching zero credentials returns descriptive error - End-to-end test: API call with
credential_querymatching multiple credentials returns descriptive error - Caching: different
credential_queryvalues produce different cache keys (existing hash-based cache handles this) - Descriptive error messages for credential selection failures (user story 13)
Blocked by
- Blocked by Credential filter chain with DCQL and default selector #4089 (DCQL CredentialSelector)
User stories addressed
- User story 1: specify which patient's credential via API
- User story 2: specify which organization type credential via API
- User story 3: only provide credential_query for ambiguous types
- User story 4: clear error on zero matches via API
- User story 5: clear error on ambiguous matches via API
- User story 6: standard DCQL syntax in API
- User story 7: self-attested credentials alongside credential_query
- User story 8: credential_query ID maps to PD input descriptor ID
- User story 12: descriptive error messages
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
[-]Add credential_query and match_policy to access token request API[/-][+]Add credential_selection to access token request API[/+]stevenvegt commentedon Mar 25, 2026
Scope update: This issue now covers
credential_selection(named parameters) instead ofcredential_query(DCQL). See updated PRD in #4067 (comment).The API parameter changes from a DCQL query array to a simple
map[string]stringmapping PD field IDs to values. The wiring through the call chain (API → client → wallet → presenter → builder) remains the same — code on branchfeature/4090-api-credential-queryis reusable with minimal changes.Blocked by #4120 (selection selector, replaces #4089).
#4090: RED — e2e test for credential_query selection
#4090: Wire credential_query through API to presenter
#4090: Wire credential_selection through API to presenter
#4090: Fix shellcheck issues, add presenter credential_selection test
#4090: RED — e2e test for credential_query selection
#4090: Wire credential_query through API to presenter
#4090: Wire credential_selection through API to presenter
#4090: Fix shellcheck issues, add presenter credential_selection test
#4090: RED — e2e test for credential_query selection
#4090: Wire credential_query through API to presenter
#4090: Wire credential_selection through API to presenter
#4090: Fix shellcheck issues, add presenter credential_selection test
#4090: Wire credential_selection through API to presenter (#4122)
#4120: Selection CredentialSelector — filter candidates by PD field I…
#4088: CredentialSelector extension point in PD matcher (#4098)