Open michaeldnelson opened 6 years ago
I can’t see anything in that spec that suggests that you can’t/shouldn’t use the client_id as the aud
. Do you have any specific concern with this @michaeldnelson?
I think you are right that this is not explicitly prohibited. Closer reading of the spec leaves this open for interpretation. I've just never seen it used this way. Personally my issue with this is that I validate the audience claim against $request->getHost(), this is a simple added layer of validation that doesn't require a database lookup. This is particularly useful if a token should be locked to a specific subdomain. Again this can all be validated with client id, it's just a little weird to me because I would consider that who is using the token, not the audience of the token. Additionally validation using the client id requires a db lookup, where host alone does not. But, as I said, I was wrong to assume this was "incorrect" it just was just cognitive dissonance for me and a challenge for my use case.
There is a cid claim for this purpose it looks like.
https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-12#section-4.3
4.3. "cid" (Client Identifier) Claim
The "cid" claim carries the client identifier of the OAuth 2.0 [RFC6749] client that requested the token.
The following example illustrates the "cid" claim within a JWT Claims Set indicating an OAuth 2.0 client with "s6BhdRkqt3" as its identifier.
{
"aud":"https://consumer.example.com",
"iss":"https://issuer.example.com",
"exp":1443904177,
"sub":"user@example.com",
"cid":"s6BhdRkqt3"
}
@michaeldnelson the last link you posted is for a draft version that has not been finalised yet I believe.
I think you might be right that the aud
should be set to the authorization server endpoint. It looks like it has been incorrectly set to identify the client instead. We aren't, to my knowledge, officially implementing RFC 7523 at present but we are following the JWT RFC which confirms your assertion about the aud claim.
Altering this would be fairly tricky though as it would break BC. I think it probably is something that needs addressing but careful thought would be needed to not immediately invalidate all active access tokens.
Thank you for taking the time to consider this issue :) I'll look forward to seeing how the project progresses.
I agree with @michaeldnelson that we should use the cid
claim for the client_id and that aud
should actually be a list of the resource servers who are the recipient of the token. However, this would require the user to pass in a list of all resource servers (which may be the same server, or a very long list of servers). This would possible require adding a new Repository to keep track of resource servers.
For simplicity, and because aud
for client_id is not strictly wrong according to the standard, although it hinders checking if the tokens are meant for that resource server (that would only be fixed if you specify the server in the request), I would not - at least soon - change the current behaviour.
Just my 2 cents.
While the RFC is in draft it should not be used, it explicitly says so in the draft.
While eventually something will be standardised, oauth2-server should refrain from adding uncertain/uncomplete features. I've checked what the larger vendors use in their JWTs, as far as I could find nobody uses cid
for the suggested purpose (yet).
If they use something it is usually referring to claims in an ID token. Which is OpenID spec, which is not supported (yet?) through the oauth2-server. For ID tokens the aud
claim MUST be the client_id
of the client requesting the token, but they also should not be used by resource servers to authenticate requests.
http://openid.net/specs/openid-connect-core-1_0.html#rfc.section.2
I'm guessing that this ambiguity resulted from the original specs being less specific and because those tokens were typically used by resource servers that traditionally fairly tightly coupled to the same vendor that distributed the tokens, it didn't really matter. What is clear though, is that no large vendors are using the aud
claim in access tokens to store the client_id
, but you can always add your own claim to remedy that.
Maybe an option to correct this behaviour / allow people to add their own claims would be an option until this can be fixed in the default setting?
Today while trying to get this discrepancy documented I reviewed the information in several specs and I think it is useful to clarify a few things.
The specification referenced by @michaeldnelson is something else The final version of the spec can be found here, and basically describes how to retrieve access tokens using JWTs from an authorisation server. It is used for 2 legged authentication scenarios (like the client credentials grant), usually where some kind of impersonation of specific users by a client without direct user input is used.
It is unrelated to the JWT contents in context of an access token used to communicate with a resource server.
The actual implemented specs neither explicitly define the JWT claim contents The two RFCs that this library does explicitly implement are "JSON Web Token" describing the generics of a JWT and the OAuth2 specific "Bearer Token Usage".
The first defines the generic usage of a small list of claims, the latter doesn't even mention JWT and predates it by years.
I've tried to find specifications that do touch upon this but could not find anything. Even OIDC does not go into this, probably because they consider it a problem of the resource server implementation. When you look at how explicitly id tokens are defined, it is a world of difference. If the wide range of implementations between authorisation servers is anything to go by, this might be a good candidate to make a specification for though.
JSON Web Token (RFC7519)
JSON Web Token (JWT) is a compact claims representation format
intended for space constrained environments such as HTTP
Authorization headers and URI query parameters.
What it does say about audience:
The "aud" (audience) claim identifies the recipients that the JWT is
intended for. Each principal intended to process the JWT MUST
identify itself with a value in the audience claim.
The interpretation of audience values is generally application specific.
So, this can be an array, with values that are of type string or uri. It also states that all principals intended to process the JWT MUST be in this property. From the OAuth2 core spec we know that access tokens are usually opaque to clients, so they themselves should not need to process the token. The client could still also be an audience, but that probably means you actually want an (OIDC) id token which is explicitly meant for use by clients.
It is ultimately left to specific implementation to define exactly what the audience actually is.
Bearer Token Usage (RFC6750)
This specification describes how to use bearer tokens in HTTP
requests to access OAuth 2.0 protected resources.
This document does not specify the encoding or the contents of the
token; hence, detailed recommendations about the means of
guaranteeing token integrity protection are outside the scope of this
document.
What it does say about audience (threat mitigation, summary):
To deal with token redirect, it is important for the authorization
server to include the identity of the intended recipients (the
audience), typically a single resource server (or a list of resource
servers), in the token.
Issue scoped bearer tokens: Token servers SHOULD issue bearer tokens
that contain an audience restriction, scoping their use to the
intended relying party or set of relying parties.
This quite clearly defines the resource servers as the audience, within the scope of OAuth2 access tokens. So believe this to be the most usable information to base the library implementation upon. But the bearer token usage spec does predate the JWT spec by years.
Though, if a future specification would actually elaborate what is what in at least the generic claims that can be present in a JWT that should be leading (anyone have time for that?).
Conclusion The OAuth2 server should and does make a stance here as specifics in this area are left to implementations. Having the client id in the audience is not wrong per-se, but resource servers should be added (config array / resource server repository interface?) as audiences too.
That way resource servers can verify the tokens are intended for their usage, which is something they MUST do according to the combined specifications, when the aud
claim is present.
The appears to expect the client identifier as audience which seems to conflict with the bearer spec here. It's possible I am misunderstanding this spec as it is possible to reject a token based on the relationship between client_id and authorization server but that is not clear to me.
https://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-12#section-3