discussion OAuth/OIDC: accepted flows and grants
Current requirements are in https://github.com/OWASP/ASVS/blob/master/5.0/en/0x51-V51-OAuth2.md#v511-authorization-server
From different discussion and comments, there have been recommendation which flows should be disallowed (e. g. password grant, implicit flow)
In https://github.com/OWASP/ASVS/issues/996#issuecomment-1858764702 I proposed to take step to the future and adapt OAuth 2.1, which means allowing only PKCE to be used.
In this context, it means - we just require everyone to use only PKCE flow for public OAuth clients (the so-called "Standard Authorization Code flow" is not good enough). It also disallows using implicit flow and password grants.
From @deleterepo in https://github.com/OWASP/ASVS/issues/1969 "proposal 1"
Verify that the Implicit Flow grant is not used or configured by the Authorization Server, as it is vulnerable to access token leakage and access token replay attacks.
This applies to both OAuth and OIDC. As per https://oauth.net/2/grant-types and https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#name-implicit-grant. If preferred we can consolidate this with 51.1.6 about Resource Owner Password Credentials Grant, but it might make sense to make it a separate requirement to keep it granular, because these grants are vulnerable to different attacks that we are highlighting.
So my proposal is, that we accepting only PKCE.
Questions to solve:
- Is it worth mentioning, that the password grant and implicit flow are known to be insecure in a requirement text, or is a chapter text enough for that?
- Is there any need to limit the scope for the requirement (accept only PKCE) - such as other flows are allowed in certain conditions?
There are other grants that we need to allow for, such as the Client Credentials grant used by clients to access resources about themselves rather than to access a user's resources, or in other words machine-to-machine authorization. This is documented in the OAuth 2.1 spec here: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-10#section-1.3. PKCE is an extension of the Authorization Code grant and this grant can't be used in all cases.
I know that positive requirements are preferred, but in this case if we want to keep it simple, it would probably make more sense to document which flows are legacy due to their insecure nature rather than state all of the accepted flows. I agree that Authorization Code Flow with PKCE is preferred when used in the right context though.
The way I see it there are two options:
- Have specific requirements about which flows/grant types should not be used.
- List the accepted flows/grant types, noting that this will require more maintenance moving forward if more flows are deprecated.
If searching solutions from grant/flow allow-list or black-list, my brain goes to endless loop.
For brainstorming - maybe we should not talk about flows and grants at all, but the reasons and attack vectors, and why those got deprecated. For example, "you need to have a defense against authorization code injection", but how do you do it without PKCE? At the same time, an authorization code injection attack is available, if an attacker can access the token endpoint. If BFF is used, the likelihood is so small, that personally, I would not put the requirement there (based on my current knowledge).
it would probably make more sense to document which flows are legacy due to their insecure nature rather than state all of the accepted flows
Yes, it would. Especially since new flows could be added later on.
For example, we wouldn't want to disallow CIBA.
In case @damienbod doesn't find the way here, I copy the argumentation provided in https://github.com/OWASP/ASVS/issues/1969#issuecomment-2128705409:
A confidential Implicit Flow grant is fine to use if only the id_token is returned and no access tokens are used/allowed in this flow.
This is sometimes required.
A confidential Implicit Flow grant is fine to use if only the id_token is returned and no access tokens are used/allowed in this flow.
This is a very controversial statement. Some counterpoints:
- Confidential clients are server-side applications that are capable of maintaining the secrecy of client credentials. Using Implicit Flow here seems redundant since confidential-server-clients can securely handle the Authorization Code Flow.
- Even the exposure of an ID token alone can be risky because it often contains sensitive information or can be used in ID token injection attacks
- This approach may be considered in controlled environments where the communication between the client and authorization server is tightly secured. However, this is a very rare scenario and not recommended as a general practice.
This approach may be considered in controlled environments where the communication between the client and authorization server is tightly secured. However, this is a very rare scenario and not recommended as a general practice.
Hi @jmanico, thanks for your feedback. The third point is the only use case I was thinking about. (no access token used in the flow)
Example of usage: id_token exchange for external MFA between 2 IdPs
Example of usage: id_token exchange for external MFA between 2 IdPs
Why would you not want to use the authorization code with PKCE in this case?
I think discussion is solved via #2043 / #2096 with modified requirement:
| # | Description | L1 | L2 | L3 |
|---|---|---|---|---|
| 51.2.5 | [ADDED] Verify that for a given client, the authorization server only allows the usage of grants that this client needs to use. Note that the grants 'token' (Implicit flow) and 'password' (Resource Owner Password Credentials flow) should no longer be used. | ✓ | ✓ | ✓ |
Any not covered aspects from this issue?