Locating claims at another source
All domains, identifiers, and tokens in these examples are fictional.
Northfield's statement in the Aggregated claims lessons was made in September and lasts until 31 January. If you left the university in October, the printer would go on giving you the student discount for months, because the statement it received would still be genuine and unexpired.
A statement that goes out of date
An aggregated claim is a snapshot. It records what the claims provider believed when it signed, and it travels unchanged until it expires. That suits facts that rarely change, or ones a relying party only needs approximately. Enrollment changes during a term, and Northfield would rather each application asked when it needed to know.
The photo service has its own reason to prefer a different arrangement. Holding signed statements from universities, banks, or employers means storing more about you than its own service needs, and keeping each statement current. It would rather tell the printer where to ask.
Distributed claims do exactly that. Instead of the statement itself, the OpenID Provider sends a reference: the address of an endpoint at the claims provider, and usually an access token that lets the relying party fetch the claim there. The relying party makes the request itself and receives the statement directly from the claims provider.
Reading a reference
When you choose the student discount and agree to share your enrollment, the photo service now answers the printer's UserInfo request like this, with the remaining profile claims left out:
HTTP/1.1 200 OK
Content-Type: application/json
{
"sub": "user-2048",
"name": "Robin Park",
"email": "[email protected]",
"email_verified": true,
"_claim_names": {
"https://id.northfield.example/enrolled": "src1"
},
"_claim_sources": {
"src1": {
"endpoint": "https://id.northfield.example/claims",
"access_token": "demo-northfield-token-4"
}
}
}
The two special members work as they did for aggregated claims. _claim_names maps the claim name to a source label, and _claim_sources holds the source under that label. This time the source has no JWT member. It has two others:
endpoint, which is required, is an OAuth protected resource at the claims provider. The specification requires it to return the claim as a JWT, and the printer expects that JWT to carry Northfield's signature, just as an aggregated statement does.access_token, which is optional, lets the relying party call that endpoint with an ordinary bearer token, sent in theAuthorizationheader. Claims providers must accept the token there.
The source object alone tells the printer which kind of claim it is reading: a JWT member for an aggregated claim, an endpoint member for a distributed one. A single response can mix them, with normal claims from the photo service, an aggregated claim from one claims provider, and a reference to another.
Nothing has been fetched yet. At this point the printer knows only where your enrollment status can be found, according to the photo service, and holds a token it could use to ask for it. It has no statement from Northfield at all.
The access token in the reference
demo-northfield-token-4 was not issued by the photo service. A token for Northfield's endpoint has to come from Northfield's authorization server, because Northfield's endpoint is the one that must accept it. How the photo service obtains such a token is outside OpenID Connect. In this example, when you linked your Northfield account to the photo service, Northfield agreed that the photo service could request short-lived tokens that read only your enrollment status. When you agree to share it with the printer, the photo service requests one and places it in the reference.
That token is a bearer credential, and now the printer holds it. Anyone who copies it from a log, or from anywhere else it travels, can read your enrollment status until it expires. Everything Token theft and replay said about handling access tokens applies: keep it out of logs and out of anything sent to the browser, send it only to the endpoint it was issued for, and discard it once it has been used. Northfield limits the damage by issuing tokens that are short-lived, that read only this claim, and that work only at this endpoint. This one was issued at 09:20 UTC, when you agreed to share your enrollment, and expires at 09:50.
The token is optional. Without one, the relying party must obtain access another way. The specification mentions a token arranged in advance between the claims provider and the relying party, or one obtained out of band, and allows the claims provider to ask you to sign in or approve the release again. Each of those means more arrangements directly between the printer and Northfield, which is much of what the reference was meant to avoid.
Aggregated or distributed
The two forms make different trade-offs for the same statement:
| Question | Aggregated | Distributed |
|---|---|---|
| How current is the statement? | As of when the claims provider signed it, possibly weeks earlier. | As of the moment the relying party asks. |
| Who learns that the printer asked? | The photo service. Northfield signed the statement once and never sees where it goes. | Northfield as well, every time the printer fetches the claim. |
| What must work when the printer needs the claim? | The printer, and Northfield's published keys. | Northfield's endpoint, and an access token that is still valid. |
| What does the printer have to handle? | A signed statement. | A bearer token for another service's endpoint, and then a signed statement. |
| What does the OpenID Provider keep? | A copy of the statement. | Whatever it needs to obtain tokens from the claims provider. |
The privacy row cuts both ways. With an aggregated claim, the university never learns which applications you shared your status with. With a distributed claim, it learns about each request: when it was made, and which relying party made it. That may be more than you expected to share when you agreed to show the printer you are a student, and the printer can only limit it by asking rarely.
The OpenID Provider chooses which form to send, sometimes by agreement with the relying party, and a provider that offers both lists them in claim_types_supported. A relying party should be ready for whichever form its providers use, with the same configuration of trusted claims providers behind both. Retrieving and validating distributed claims follows the printer as it uses the reference at checkout.