Resources¶
A client names, in resource, the resource server it intends to call, and its access token is issued for
that audience rather than for everything the client might reach (RFC 8707 §2). A resource server that
receives a token addressed elsewhere has what it needs to refuse it. A request made for a person that names no
resource gets a token addressed to the client itself, which is the token UserInfo accepts.
Registering resources¶
beffroi:
clients:
billing:
# ...
resources:
- 'https://api.example.com/'
- 'urn:example:ledger'
resources is the closed list of what a client may ask a token for, with no pattern and no wildcard. Each
value is an absolute URI (RFC 3986 §4.3) without a fragment. A query is allowed, RFC 8707 §2 recognising that
it is sometimes what scopes the request, and a URN is a resource as an HTTPS URL is: a resource is an
identifier, which the provider never fetches. What a request names is compared byte for byte with the list.
A client that registers no resource asks for none. Only a declaration writes the list: a client that
registers itself and sends resources is refused with invalid_client_metadata,
so it asks for none either.
Asking for one¶
At the authorization endpoint and at the pushed authorization request
endpoint, resource may be sent several times, once per resource, which no
other parameter may:
GET /authorize?response_type=code&client_id=billing&...
&resource=https%3A%2F%2Fapi.example.com%2F
&resource=urn%3Aexample%3Aledger HTTP/1.1
In a request object, the same claim carries a list of strings. A value named twice
counts once. A value that is not an absolute URI without a fragment, and a resource the client did not
register, are both invalid_target, at the redirect URI of an authorization request and as JSON at the
pushed request endpoint; the description names no resource, what a client registered being nothing an error
teaches whoever sent the request. A request that names none asks for none, and nothing is filled in from the
registration: a token valid at several resources is valid at each of them (RFC 8707 §3), so it is asked for
and never assumed.
The resources named travel with the authorization: the code carries them, and the token endpoint may narrow them and never widen them.
What the access token says¶
| Resources asked for | None asked for | |
|---|---|---|
aud of the access token |
The resources, a string for one and a list for several (RFC 7519 §4.1.3) | The client_id |
client_id of the access token |
The client, whatever the audience | The client |
aud at the introspection endpoint |
The same as the token | The same as the token |
| UserInfo | Refused, invalid_token with a 401: the token is addressed to a resource of its own and not to this provider |
Answered |
The opaque shape of access token is described by the introspection endpoint with the same aud. When the
provider reads a self-contained token of its own back, it accepts in aud only the client itself and the
resources that client registered, so a value it would never have written is refused before anything else is
believed.
At the token endpoint¶
| Grant | A resource named |
None named |
|---|---|---|
authorization_code, refresh_token |
Narrows the access token of this response to those, among the ones the authorization carries. The refresh token stays bound to them all, so a later refresh may ask for another of them | The resources of the authorization |
client_credentials |
Among the ones the client registered | Refused with invalid_target: a token with nobody behind it is addressed to a resource, or it is not issued |
| JWT bearer | Among the ones the client registered | Refused with invalid_target |
| Token exchange | Narrows to some of the resources the presented token is addressed to | The resources of the presented token. One addressed to its client and to no resource has none to pass on, and is not exchanged |
A resource outside what the line allows is invalid_target, in the JSON of the token endpoint. A token
exchange is held to the registration of the client that asks as well: the resources its access token is
addressed to, and the scopes it carries, are ones that client registered, so an exchange never reaches a
resource or a scope its registration does not name. The device
authorization endpoint and the backchannel authentication endpoint read resource when the flow starts,
against the resources the client registered, answering invalid_target in their own JSON, and a request that
names none there gets a token addressed to the client, a person being behind those flows.
What the tenant announces¶
What a tenant announces as its protected resources is read from the clients that registered one, never from
a list kept beside them, and it is the protected_resources member of RFC 9728 §4: the one member of the
registry that says what the values of a resource parameter are, RFC 8707 registering none of its own. Every
resource a client of the tenant registered is in it, each once. A tenant whose clients registered none
announces nothing rather than an empty list, which a client would read as "no resource is acceptable here".