Repository navigation
fix: release PID claims for the pid, pid_1_5 and pid_1_8 scopes - #22
Merged
Merged
Conversation
These three scopes have been advertised in scopes_supported all along with no
handler behind them in claimsForScopes. A request naming one - which is
exactly what vc's apigw sends, one credential type at a time
(Scopes: []string{session.CredentialType}) - matched none of
profile/email/organisation/ehic, fell through to the backwards-compat block
and released four claims:
map[email:... family_name:... given_name:... name:...]
No birthdate, no nationality, no place of birth, no issuing authority. Not
enough to build a PID from, so the issuer rejects the credential request
outright. Advertising a scope the OP has no claims for is the bug; a client
has no way to discover that the scope is inert.
ARF 1.5 and ARF 1.8 describe the same person under different claim NAMES, and
apigw uses the OIDC claims verbatim as the credential's document data, so a
claim under the other version's name simply isn't present to disclose and a
verifier's DCQL query for it won't match. The two therefore get separate
branches rather than one shared set:
ARF 1.8 ARF 1.5
place_of_birth birth_place
nationalities [] nationality (single)
age_equal_or_over age_over_NN (flat booleans)
The unversioned "pid" scope follows ARF 1.8, the current version. A request
naming several of these is not meaningful - they are three spellings of one
credential - so the switch lets the most specific win rather than having one
overwrite the other's differently-named claims. All three are added to the
backwards-compat guard for the same reason "ehic" was: otherwise the block
below overwrites what the handler just set.
Age attributes are derived from birthdate rather than stored per user, so they
cannot go stale as the fixture data ages. Without them a verifier asking for
age_over_18 (1.5) or age_equal_or_over.18 (1.8) finds nothing to match, since
DCQL requires every requested claim to be present. The birthday comparison
uses month/day, not day-of-year: in a leap year every date after February
shifts by one day-of-year, which would report the wrong age for a full day
around each such birthday.
Tested: both vocabularies release their own names and none of the other's; the
unversioned scope tracks 1.8; a user with no birthdate yields no age claims at
all rather than empty ones; and the boundary case is checked on the day
before, of, and after a birthday. The fallthrough regression test was
confirmed to fail against the previous behaviour, reproducing the exact
four-claim map above.
|
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.



The bug
pid,pid_1_5andpid_1_8are advertised inscopes_supported, butclaimsForScopeshas never had a handler for any of them. A request naming one — which is exactly what vc's apigw sends, one credential type at a time (Scopes: []string{session.CredentialType}) — matches none ofprofile/email/organisation/ehic, falls through to the backwards-compat block, and releases four claims:No birthdate, no nationality, no place of birth, no issuing authority. Not enough to build a PID from, so the issuer rejects the credential request outright. Advertising a scope the OP has no claims for is the bug — a client has no way to discover that the scope is inert.
Why 1.5 and 1.8 need separate branches
They describe the same person under different claim names, and apigw uses the OIDC claims verbatim as the credential's document data. A claim under the other version's name simply isn't present to disclose, and a verifier's DCQL query for it won't match.
place_of_birthbirth_placenationalities(list)nationality(single)age_equal_or_over.NNage_over_NN(flat booleans)The unversioned
pidscope follows ARF 1.8, the current version. A request naming several of these is not meaningful — they are three spellings of one credential — so theswitchlets the most specific win rather than having one overwrite the other's differently-named claims. All three are added to the backwards-compat guard for the same reasonehicwas: otherwise the block below overwrites what the handler just set.Age attributes
Derived from
birthdaterather than stored per user, so they can't go stale as the fixture data ages. Without them a verifier asking forage_over_18(1.5) orage_equal_or_over.18(1.8) finds nothing to match, since DCQL requires every requested claim to be present.The birthday comparison uses month/day, not day-of-year: in a leap year every date after February shifts by one day-of-year, which would report the wrong age for a full day around each such birthday.
Testing
go build,go vet,gofmtand the full suite pass. New coverage:The regression guard was verified against the previous behaviour by reverting only the dispatch (leaving the helper in place so it still compiles) — it fails and reproduces the exact four-claim map above.
Context
Found while debugging an unrelated credential-issuance failure. This one is currently dormant, not the cause of that: vc's apigw sends
openid profilefromauth_providers.oidc.scopes, so today it hits theprofilebranch. It becomes live the moment an issuer requests the credential type as the scope, as theehicpath already does.🤖 Generated with Claude Code
https://claude.ai/code/session_01Cm287nVbhUoBhvVqSMbNCb