As promised on the WG call, I’ve gone through the 2.1 document and I’ve made 
some notes and suggestions on my way through. A big thanks to the editors for 
putting this together, and particularly for Aaron who did the early heavy 
lifting on getting a reasonable start on this important work!

But first, a note: I realize that many portions of this are simply copied from 
6749 or related specifications, and I do not fault the editors for that. Even 
so, there are some places where the old language should be updated in this 
draft, since we have an opportunity to fix things and make them more readable 
on our way through. There are also a number of places that are redundant with 
each other as they clearly come from different source documents. A major goal 
of this work is to coalesce these differences into a single and easily 
understandable framework.



§Abstract

I think we should update “interaction between the RO and the HTTP Service” to 
be “the RO and an authorization service” or something like that instead, since 
“the HTTP service” referenced elsewhere in this paragraph is more precisely the 
RS and not the AS, yet the interaction and approval happens at the AS. OAuth 
2.0 allowed the AS and RS to be separate, and 2.1 should go further to admit 
that in a lot of cases today, they are separate. 

There’s been debate on the “replaces and obsoletes” language already, and I 
think there’s a lot of IETF process that we’ll need to sort out to get that 
language right.


§1: We should add a note on password use to this list:

 - Often the resource owner’s password is used with other unrelated services, 
and the additional exposure of sharing the password among components in one 
domain lowers the possible security in other domains where the password is 
shared.


  ¶3/4 can probably be collapsed to read better, and some of the language 
cleaned up. Recommend:

OAuth addresses these issues by introducing an authorization layer and 
separating the role of the client from that of the resource owner. In OAuth, 
the client requests access to resources controlled by the resource owner and 
hosted by the resource server. Instead of using the resource owner's 
credentials to access protected resources, the client obtains an access token - 
a credential representing a specific set of access attributes such as scope and 
lifetime. Access tokens are issued to clients by an authorization server with 
the approval of the resource owner. The client uses the access token to access 
the protected resources hosted by the resource server.

  ¶6: (and throughout document) avoid use of gendered pronouns in favor of 
singular “they” unless needed for clearer reading (such as an Alice and Bob 
scenario)

§1.2: This diagram could use an update to not show the client talking directly 
to the RO in the first step, especially because the ROPC grant has been removed 
here. The way it’s written now makes it look like the user gives something to 
the client which it then trades for a token directly, which doesn’t happen 
quite like that anywhere.

§1.3: Having taught many OAuth 2 classes to hundreds of people over the years, 
I can say with confidence that this definition of “grant” as a credential has 
historically been problematic and confusing to most people. And in particular, 
it doesn’t even really apply to the client credentials flow listed here: there 
is not a separate "credential representing authorization", just the client’s 
own authentication. Suggest new text to more accurately reflect what a “grant” 
is in the OAuth reality:

An authorization grant is a process by which a client obtains authorization 
from a resource owner to obtain an access token to act on that resource owner’s 
behalf. This specification defines...

Changing this would require a consensus call 

§1.3.X: I don’t see why we shouldn’t list the Device Flow here in this spec. 
It’s mentioned as an extension later, but we might as well list it here as a 
known and accepted grant type. 

§1.4: This section should mention introspection explicitly. Recommend rewriting 
the intro to ¶3:

The token make be used by the RS to retrieve the authorization information, or 
the token may self-contain the authorization information in a verifiable manner 
(i.e., a token string consisting of a signed data payload). One example of a 
token retrieval mechanism is Token Introspection [RFC7662], in which the RS 
calls an endpoint on the AS to validate the token presented by the client. One 
example of a structured token …

We may also want to mention CWT (RFC8392) here in passing. 

§1.5: “The string is usually opaque” should be “the string is opaque"

§1.6: this should probably refer to the TLS BCP195 here instead of the RFC and 
version.

§1.8: This should have explicit links to introspection (RFC7662), registration 
(RFC7591, RFC7592), and discovery (RFC8414) inline as they’re given as 
examples, instead of putting them all in the appendix. Perhaps also bring up 
JWTs for token formats here as well.

§1.X: Suggest adding a section on compatibility with OAuth 2.0, either as part 
of §1.8 or in a new section injected right after it. Some suggested starter 
text:

OAuth 2.1 is compatible with OAuth 2.0 with the extensions and restrictions 
from known best current practices applied. Specifically, features not available 
in OAuth 2.0 core, such as PKCE, are required in OAuth 2.1. Additionally, 
features available in OAuth 2.0, such as the implicit or resource owner 
credentials grant types, are not available in OAuth 2.1. Furthermore, some 
behaviors allowed in OAuth 2.0 are restricted in OAuth 2.1, such as the strict 
string matching of redirect URIs required by OAuth 2.1.

§2: the client needs only provide redirect URIs if it uses them — this 
registration requirement is meaningless for device flow and client credentials 
grants, suggest changing second bullet to something like:

        - provide client details needed by the grant type in use, such as 
redirect URIs as described in section 3.1.2, and

§2.1: The first sentence on client IDs seems out of place here, and it should 
probably be in 2.2 or 2 itself. It might read better to move §2.1 after §2.3 to 
allow getting away from that problem

§2.2: While it’s usually the case that the AS issues the client_id, it’s 
increasingly common in profiles of OAuth 2 for that to no longer be true. 
Ultimately, the AS needs to be able to :recognize: the client software 
identified by the client ID, and issuing an ID associated with some known set 
of policies (like which redirect URIs are allowed) is just one way to do it. We 
should be more precise in the definition and allow for the more general use 
cases that we already know are in the wild. Additionally, fixed client IDs are 
a thing, and so the restriction of it being unique to the AS is also untrue. 
Now allowing client_id choice is important mostly for registration-based 
clients, where the AS does issue the ID, and not for other cases where the AS 
“recognizes” and processes the client ID, like in OIDC’s Federation profile and 
some other specs.

§2.3.1: Can we excise the term “client password” since nobody in the wild uses 
it, in my experience at least? 

§2.3.X: We should mention other common client authentication methods here in 
the core, including private_key_jwt and MTLS. Both have stable implementations 
and are registered, we should call them out directly.

§2.4: We need to define what exactly an “unregistered client” is if we’re going 
to refer to it here. I think rewriting of §2.2 could help address a lot of this.

§3.1: Since the “resources” parameter spec (RFC8707) breaks the “not more than 
once” requirement, can we change that here? Or at least put in an escape valve 
like “extensions to this specification MAY define parameters that can be 
included more than once”.

§3.1.2: Comparing “two URIs” is talked about here, but only one is explicitly 
mentioned. I assume it means comparing the registered redirect URI vs. any 
specified in the request, but that’s not mentioned. This is misplaced — maybe 
move to §3.1.2.3 or the information needs to be inlined up here.

§3.1.2.5: If we’re going to mention this kind of attack here (and we should), 
then we should also talk about exposure of the auth code in referrer headers, 
especially to elements loaded within the page (such as images and other 
non-script data). 

§3.2: Again the use of “grant” as a noun here largely leads to confusion. This 
could be changed to just “The token endpoint is used by the client to obtain an 
access token using a grant, such as those described in §4 and §6 of this 
specification.”

  ¶3: The client shouldn’t ever be adding query parameters to the token 
endpoint, so this requirement is not meaningful.

  ¶5: We should specify form encoding as the input body here.

  We should be explicitly recommending CORS support on the token endpoint here, 
especially if we expect SPA’s to use the auth code flow going forward.

§3.3: Can we start to mandate or at least recommend that scope is always 
returned and not just when it differs? Yes this is a breaking change for the AS 
but it doesn’t affect clients negatively, and it’s similar in requirement to 
doing exact redirect URI matching which is already done in this spec that OAuth 
2.0 didn’t do.

§4: As above, stating that the authorization is “in the form of a grant” is 
confusing as the authorization might be just the existence of the client itself.

§4.1: We should remove the “flow” based language throughout the document. This 
seems to have never quite gotten cleaned up previously. 

§4.1: The requests aren’t coming “From the authorization server”, suggest 
reword: … capable of receiving incoming requests (via redirection from the 
authorization server).

§4.1.1.1: The first code-block callout is unhelpful here, suggest inlining it 
to the preceding paragraph, or remove it. The content is largely already 
covered by the ABNF and the NOTE.

§4.1.1.2: Reverse the order of the plain and S256 examples to imply preference 
to S256. Remove line about “existing deployments”, but constrained environments 
is still a potentially reasonable reason to keep “plain” so add that to the 
preceding paragraph (though you’d be hard pressed to find an embedded system 
that can’t do that these days). 

§4.1.2: the last few paragraphs on storing code_challenge are awkward to read, 
suggest reordering to clarify:

The authorization server MUST associate the code_challenge and 
code_challenge_method values with the issued authorization code so the code 
challenge can be verified later. 
The exact method that the server uses to associate the code_challenge with the 
issued code is out of scope for this specification. The code challenge could be 
stored on the server and associated with the code there. The code_challenge and 
code_challenge_method values may be stored in encrypted form in the code 
itself, but the server MUST NOT include the code_challenge value in a response 
parameter in a form that other entities can extract.

§4.1.2.1: We should state here, or somewhere in §4.1, that a client might send 
a request and never get a response back on the front channel, and they have to 
be prepared for that. 

    ¶3: This should be folded into the error definition below instead of its 
own paragraph.

   Should we state in here the “unsupported_response_mode” error or other 
now-registered errors from the registry?

§4.2.1: This section should be dropped, it doesn’t add anything to the 
conversation. It was meant to keep things parallel to the other three grants 
listed, but now that there’s only one it is just superfluous. 

§4.X: Again I think we might want to list the device flow here as more than an 
example. If this is meant to be one-stop-shopping then we should have 
everything reasonable in the list.

§5.1: Move the content type to the opening sentence instead of below, but keep 
the discussion of serialization and structure down where it is in ¶3_

    The JSON reference should be updated to RFC8259

§6: I wonder if now we should move this back to a “grant” type in §4. It 
originally was but the editor moved it out to its own section, but I have found 
that it confuses developers who are looking for it to have it on its own. 
Semantically it’s a grant (process to get an access token), but it feels like 
something “special” where it isn’t really.

    I don’t understand the allowance for allowing clients to refresh a token 
with alternate grant types here. In particular, the example of a long-lived 
authorization code being used again is illegal since an auth code is 
one-time-use as per §9.8 and elsewhere. If the client is just getting another 
access token by doing a new grant process, this isn’t “refreshing” the access 
token, it’s getting a new one from scratch. What is this new allowance trying 
to say or enable?

§6.1: I’m not sure of the value of including the “implementation note” listed 
here, especially because “grant” is now being used as an ongoing entity and not 
as currently defined in the document nor as I’m proposing we more-accurately 
define it here. This seems like general advice for not trusting values in 
tokens unless you can validate the integrity of the token, and should go in 
another section. 

§7.2.2: some leftover language from this being standalone: “All challenges 
defined by this specification MUST use the auth-scheme value Bearer”. Change to 
“all challenges for this token type…”

§7.3: This section should probably discuss the fact that a given API can have 
its own error codes and responses and doesn’t have to use the OAuth responses. 
This isn’t clear by the text, and if the intention of the original text was to 
have everyone return the same JSON error, that’s violating design principles of 
OAuth as a security layer on top of an API (and we should fix that). Either way 
we should be clear about the place of OAuth’s error messages.

§7.X I would like to see some discussion on other forms of tokens, especially 
sender-constrained token methods such as OAuth PoP, Token Binding, MTLS, and 
DPoP. 

§7.4: This section feels like it should be its own top level, or integrated 
into §9, and not under “accessing protected resources”.

§7.4.2: The beginning should explicitly reference introspection and JWT as 
possible solutions.

    The TLS recommendation should point to the BCP195.

    I’d rather see these recommendations listed out instead of mashed together 
in §7.4.2 and listed again in §7.4.3 — it’s hard to read this way.

    The recommendations here are listed for bearer tokens but largely apply to 
sender constrained tokens as well.

§8.3: The pointer to registering new parameters should point to §8.2 internally 
instead of directly to RFC6749

§9: There are several broken/missing links throughout this section, evidenced 
by surviving text like (#pop_tokens) and (#mix_up). 

§9.1: This probably means “should require clients to authenticate” not “use 
client authentication”

    ¶3 is confusing, suggested rewording: The process of issuance/registration 
and distribution of the underlying credentials MUST ensures the confidentiality 
of the credentials for an authorization server to rely on authentication with 
those credentials.

    ¶4: This advice should apply even when clients can authenticate, it’s only 
especially applicable when the client hasn’t authenticated.

    ¶6: Should back away from value-judgment language like “more sensible 
services”. Also, realize that client instances can be strongly associated even 
when using dynamic registration, so this advice falls flat in many cases in the 
wild.

§9.1.1 and §9.2 feel like they’re more closely related than their relative 
positions in the text would indicate. Should they be §9.2.1/9.2 or §9.2/9.3 
respectively instead? I can’t tell what the intent is.

§9.2: This discussion on redirect URIs for native apps should be its own 
section (§10.3 has this kind of detail), and it should also include captured 
remote URLs (registering an https URL on the app developer’s site that the app 
listens for) (this is in §10.3.2 but not mentioned here)

§9.4: Not all access token attributes should be shared with the client. In many 
cases, the user’s identity or, say, medical record number might be unknown to 
the client but known to the RS to look up information when a call is made. It 
might also be necessary to hide some attributes from some RS’s when a token is 
used for multiple RS’s in a system.

§9.4.2: The first paragraph isn’t about replay and seems to belong in §9.4.1 
instead

    I think we should have more detail on sender constrained tokens, and that 
the token value vs. the keys used to present the token can be handled 
differently by clients. Also discussion of an attack where the RS replays the 
access token would fit under such an umbrella.

§9.5: I believe “...guessed to produce valid refresh tokens” in the last 
paragraph is supposed to be “…guessed to prevent valid refresh tokens”, or 
something similar. 

§9.6: The advice here should also indicate that an AS can (should?) record 
other details with the token, including which grant type the token was issued 
under. The AS can also limit which scopes are available to which grant types 
and circumstances.

§9.7: While PAR doesn’t seem to be in scope (should it be?), it does seem that 
the use of PAR allows an AS to do something other than direct string matching 
for the redirect URI, since the client can present a redirect URI in an 
authenticated state in the back channel first, and the AS can make a more 
robust decision on those grounds. I think we might want to consider that here.

    ¶4: The “same user agent” advice only applies to web-based applications, 
and this should be made more clear. Otherwise the user isn’t interacting with 
the client via an agent, and the launch/return can be separated.

§9.9: The advice for state and scope also applies to anything sent in the front 
channel, and that should be called out more specifically here with these as key 
examples.

§9.11: What’s the goal with the “other means” requirement, and what means are 
intended here (and how do they differ?)?

§9.14: We should be more clear that this isn’t the same as registering to 
handle a :single: https URI, which is now a common and accepted pattern.

§9.16: There’s a formatting error on the example here (if I had to guess, 
someone used ``` instead of ~~~ in the markdown source)

§9.18.1: We probably want to discuss clients putting target URIs (ie, where to 
redirect to after processing the code) into the “state” value in a way that 
someone can manipulate before the callback occurs. 

§9.19: This uniqueness requirement is stronger than the suggestion earlier in 
the document. I think it should still be guidance, not a requirement, as there 
are other methods of preventing the mixup attack (like properly using 
PKCE/state together). 

§9.20: Some of this seems to be a repeat of previous sections, maybe combine 
them all into a larger discussion on user agents?

    This section should probably explicitly discuss secure browser tabs. (They 
are mentioned in passing in §10.2)

§10: Much of the content of this section is covered in §9, and these need to be 
shuffled together appropriately. (I get that they come from different specs, 
and the plan is for this spec should combine them intelligently into a 
navigable set of risks and requirements and not just paste them back to back.)

     ¶5: This is specifically talking about “The system browser”, and not just 
any external browser. This is further muddied by the fact that the user might 
not have all their sessions in the default/normal browser on the platform, a 
topic which should be discussed somewhere in here.

§10.3: I don’t understand the MUST on the three different options. Are there 
any teeth to this requirement? If a platform restricts one or more of these 
options is it not in compliance with OAuth 2.1?

§11: This section would be a good place for the discussion on the need for CORS 
support on the token endpoint.

§12: The discussion on compatibility expectations can be expanded into this 
section here.

§13: It’s not exactly traditional to do so, but it might be worthwhile to list 
out the various OAuth registries here with explanations for what they provide. 
In particular, the client metadata registry gives a client model, the AS 
discovery registry gives a server model, introspection and JWT give a token 
model, etc. 

§B: The claims in the intro are no longer true as of 2014: it’s been registered 
in https://www.iana.org/assignments/media-types/media-types.xhtml 
<https://www.iana.org/assignments/media-types/media-types.xhtml> and links to 
the WHATWG spec for it.


_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to