V51 OAuth: Add OAuth verifications for token management
Closed this issue Β· 37 comments
To address BCPs from https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps#name-application-architecture-pa a suggestion is to add the following verifications. Note that this address (closes) #1963.
V51.1 Generic OAuth2 security
Verify that tokens are only managed by nodes where it's strictly needed, in example avoid having tokens accessible for JavaScript frontends. (L1, L2, L3)
V51.2 Authorization Server
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'. Note that L1-L2 applications could also use client-secret authentication and allow public clients. (L3)
Verify that all token requests requires client authentication and that only sender-constrained (Proof-of-Posession) access-tokens are issued, either using 'mTLS certifcate binding' or 'DPoP'. (L3)
Is there any reason to open a separate issue or we can keep this discussion in #1963?
We can keep it in #1963, should I add this issue text as a comment there? And then close this one?
If here is no new perspective or reasoning, it's better to continue the discussion where it is already happening.
Closing this thread as there is already a discussion in another issue mentioned above.
I leave to @TobiasAhnoff to close to be sure all points and contents are transferred to another issue.
Verify that tokens are only managed by nodes where it's strictly needed, in example avoid having tokens accessible for JavaScript frontends. (L1, L2, L3)
"managed" is somewhat vague?
What about something like: "Verify that tokens are not sent to components which do not strictly need them. For avoid having tokens accessible for the frontend when they are only needed by the backend. (L1, L2, L3)"
Doesn't this also applies to refresh tokens? β Sorry, I misread your text :)
@randomstuff I like replacing the word "managed" and yes, this applies to refresh tokens as well (especially long lived tokens should be avoided in the frontend). How about this?
Verify that tokens are not sent to components which do not strictly need them. For example avoid having access or refresh tokens accessible for the frontend when they are only needed by the backend. (L1, L2, L3)
Based on the discussion in #2044 a suggestion is to modify/split
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'. Note that L1-L2 applications could also use client-secret authentication and allow public clients. (L3)
to also make it clear that client-authentication (for all confidential clients, including code and clients-credentials) must be sufficient for the level of security. Perhaps have two verifications like this (where the first one for all levels and the second only for L3):
Verify that all confidential clients are configured to use secure client authentication. For L1 cryptographically secure client secrets using basic authentication can be used, while stronger methods (i. e. mTLS or private-key-jwt) are only recommended. (L1,L2,L3)
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'. (L3)
I think this works, but then we have native mobile apps where it is common to have public clients (where all OAuth is done in the app). Some might use OIDC CIBA or integrate authorization for the app with other authentication protocols (in the Nordic countries this is often called BankID) which might not use OAuth at all, but sometimes this is also integrated with OAuth/OIDC.
I think it is hard to capture this in verifications because it depends on context and threat models etc...
I like having the L3 verification to say just:
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'. (L3)
And then (for L3 applications and maybe also L2?) you have to do your own risk assessment and mitigations (e g PKCE, Reference-tokens, DPoP) if you donΒ΄t follow this and introduce public client solutions or use other (weaker) client authentication methods. Or should we try and add something about native mobile apps to capture this?
Instead of technical checklist I prefer to go with something abstract.
For the context, we talk about machine-to-machine communication and mTLS authentication between services. It is away from the first level defense. We talk here about the likelihood component - what is the difference to reach to client credentials vs mTLS certificates.
We also have requirement (the category is wrong for this, but this is a separate problem):
# | Description | L1 | L2 | L3 | CWE |
---|---|---|---|---|---|
1.2.2 | [MODIFIED] Verify that communications between back-end application components, including APIs, middleware and data layers, are authenticated and use individual user accounts. | β | β | 306 |
We also have requirements:
# | Description | L1 | L2 | L3 | CWE |
---|---|---|---|---|---|
9.2.2 | [MODIFIED] Verify that an encrypted protocol such as TLS is used for all inbound and outbound connections to and from the application, including monitoring systems, management tools, remote access and SSH, middleware, databases, mainframes, partner systems, or external APIs. The server must not fall back to insecure or unencrypted protocols. | β | β | 319 | |
9.3.3 | [ADDED] Verify that mutual TLS (mTLS) is used by services communicating internally within a system or "intra-service communications" to ensure all the involved parties at each end of a network connection are who they claim to be. | β | 295 |
So do we have it already covered, just in in the OAuth context?
@elarlang, I agree we have those mTLS and TLS matters covering the points raised by @TobiasAhnoff even if they are OAuth context.
I think the requirement we have here is for:
Verify that tokens are not sent to components which do not strictly need them. For example avoid having access or refresh tokens accessible for the frontend when they are only needed by the backend. (L1, L2, L3)
Right? Or am I missing something else?
9.3.3 covers the mTLS parts of
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'. Note that L1-L2 applications could also use client-secret authentication and allow public clients. (L3)
Verify that all token requests requires client authentication and that only sender-constrained (Proof-of-Posession) access-tokens are issued, either using 'mTLS certifcate binding' or 'DPoP'. (L3)
but 9.3.3 does not address OAuth sender-constrained tokens and strong client authentication (without mTLS).
A suggestion is to try and rewrite this (perhaps merge as one) in a more general way as @elarlang suggested, and also check for overlap with other suggested OAuth verifications like in #2040
I try to get the general "token scope" requirement in. We should have "positive" requirement to say, what must be achieved (instead of saying, what must not be done).
So my proposal for this is:
Verify that tokens are only sent to components that strictly need them. For example, avoid having access or refresh tokens accessible for the frontend when they are only needed by the backend.
Section: "Generic OAuth2 and OIDC security"
@elarlang, Looks good to me.
One requirement is now in the document as:
# | Description | L1 | L2 | L3 |
---|---|---|---|---|
51.1.2 | [ADDED] Verify that tokens are only sent to components that strictly need them. For example, avoid having access or refresh tokens accessible for the frontend when they are only needed by the backend. | β | β | β |
If there is need to have changes into this requirement, I prefer we open a separate issue for that.
This issue stays open as here is another one or two requirements (#2038 (comment)) to discuss.
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'. Note that L1-L2 applications could also use client-secret authentication and allow public clients.) (L3)
Verify that all token requests requires client authentication and that only sender-constrained (Proof-of-Posession) access-tokens are issued, either using 'mTLS certifcate binding' or 'DPoP'. (L3)
With those I'm not technically that familiar (yet), but some feedback/questions.
The "Note" part we can skip
The point for the first one is to ask confidential OAuth client and strong authentication and the second, to use sender-constrained access tokens? If so, it seems that there can be some deduplication done from authentication part for the second requirement.
I really don't like the idea to allow using public OAuth clients for web applications, the same idea was risen also by @TobiasAhnoff here #2038 (comment)
And then (for L3 applications and maybe also L2?) you have to do your own risk assessment and mitigations (e g PKCE, Reference-tokens, DPoP) if you donΒ΄t follow this and introduce public client solutions or use other (weaker) client authentication methods. Or should we try and add something about native mobile apps to capture this?
Yes, the authentication part can be removed from the second verification, since the original OAuth RFC states that "If the client type is confidential or the client was issued client credentials (or assigned other authentication requirements), the client MUST authenticate with the authorization server" (see https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.3).
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'.
Verify that only sender-constrained (Proof-of-Posession) access-tokens are issued, either using 'mTLS certifcate binding' or 'DPoP'.
But note that sender-constrained does not require client authentication (and that is why the authentication part was present in the second verification to begin with).
For L3 I think the two verification are clear, but it is not uncommon to allow native mobile apps (not web or hybrid apps) to be public clients, even for L3 applications, so maybe it is too strict and ASVS should address the native mobile apps exception?
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'. Note that native mobile apps might be public clients, given that other token misuse mitigations are in place like PKCE, DPoP and reference access tokens.
For L3 I think the two verification are clear, but it is not uncommon to allow native mobile apps (not web or hybrid apps) to be public clients, even for L3 applications, so maybe it is too strict and ASVS should address the native mobile apps exception?
I'm not so convinced that "native mobile" is such an exception compared to native apps in general. Moreover, if you allow web mobile apps to be public client, why couldn't you allow some web applications to do so (such as a local JupyterLab instance). Moreover, native apps could use dynamic client registration in order to be confidential.
@randomstuff Perhaps a misunderstanding, the suggestion is to require confidential clients for L3 (not allowing any public browser-based clients), and "native mobile apps" was an example of clients that often are public (even if we want confidential clients).
Perhaps a dumb question from me, but do you agree that we should have this for L3?
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'.
Since different kinds of native apps ("non-browser" apps) can be regarded as confidential clients (can be trusted with client secretes) and they can manage them using dynamic client registration (if needed)?
@TobiasAhnoff, yes I agree.
I think I did/do not correctly understand this part:
For L3 I think the two verification are clear, but it is not uncommon to allow native mobile apps (not web or hybrid apps) to be public clients, even for L3 applications, so maybe it is too strict and ASVS should address the native mobile apps exception?
@randomstuff I understand that you (and probably others reading this) did not understand what I meant by "so maybe it is too strict and ASVS should address the native mobile apps exception"...it was a bit rough, me thinking out load and not well put...good that we sorted that!
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'.
Verifying that clients are configured to use strong client authentication is strictly weaker than ensuring that the authorization server enforces the usage of strong client authentication*. Is the verification we are stating, the verification we actually want? Do we say at some point that we verify that the authorization server actually enforces the usage of the configured authentication method?
Also I believe, that by "strong client authentication" we mean "strong client authentication based on public-key cryptography"? So we need to state if explicitly? I believe the intent here is to exclude the usage of client_secret_jwt (and any other shared-secret based client authentication)?
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'.
Added comment from #2042 (which is somewhat redundant with previous comment).
This one currently does not explicitly includes the verification that the authorization server actually enforces the usage of the strong authentication method. As an auditor, checking that the client actually sends the strong authentication it one thing but what we really ought to do is to check that the authorization servers actually checks that authentication.
I already happened to find cases (not in OAuth) where the client was authenticating allright but at some point I found (out of pure luck actually) that the server was actually not configured to require authentication at all :)
As discussed in #2042, we would not want to repeat in the PAR section: "The authorization server must enforce client authentication for the PAR endpoint for confidential clients." On the other hand, we might want to make sure that the PAR endpoint, the revocation endpoint and so on are indeed protected by client authentication. So, would it be a good idea to include some examples here? Something in the line of,
β¦ for backchannel endpoints such as the token endpoint, the token revocation endpoint, the PAR endpoint, the CIBA backchannel authentication endpoint, etc.
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'.
This is requirement for the client. Can we write the requirement for the authorization server that
Verify that the authorization server requires the client to be confidential and use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'.
Changes:
- we need to be sure, that is required not optional for the client
- "all clients" > "the client" - from the ASVS scope we should watch certain communication between the Client and the AS.
Need to add here the comments / feedback from #2038 (comment).
From #2038 (comment) - this one is covered somewhere else or should be added as well?
Verify that all clients are confidential and configured to use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'.
I think this needs to be added and that written for the authorization server is preferred (as suggested above)
Verify that the authorization server requires the client to be confidential and use strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'. (L3)
Thinking more about it:
Verify that the authorization server requires the client to be confidential ...
https://datatracker.ietf.org/doc/html/rfc6749#section-2.1
Clients capable of maintaining the confidentiality of their credentials (e.g., client implemented on a secure server with restricted access to the client credentials), or capable of secure client authentication using other means.
How the authorization server technically can require it?
We have discussion over (#2038 (comment)) 2 L3 requirements here:
Verify that the client is confidential and the authorization server requires the use of strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'.
Verify that the authorization server issues only sender-constrained (Proof-of-Posession) access-tokens, either using mTLS certifcate binding or Demonstration of Proof of Possession (DPoP).
I would like to get some at least relatively ok versions into repo and open separate issues for each requirement if further discussion is needed.
How the authorization server technically can require it?
- By forcing a client registration and approval process (usually just a one time event) (Some registration processes can require a full audit of the client if the server owner wants)
- By forcing client authentication like mTLS or other client secret
My point is, that if the client uses client credentials, you can not force the client to be confidential on the authorization server side. One may use client credentials from the browser, which makes it a public client, but based on the RFC, this is a concept, not a technical term. From the requirement point of view - you need to verify separately, that the client is a confidential client and you can not verify it from the authorization server.
I get it. That makes total sense. RFC 6749 says that the client type is determined by its ability to securely maintain its credentials, not by any inherent technical enforcement by the authorization server.
ping @TobiasAhnoff @randomstuff - please check the latest proposal in #2038 (comment)
Looks good to me. I am wondering if "strong client authentication method" would need be reworded to be more precise.
Goes in as:
# | Description | L1 | L2 | L3 |
---|---|---|---|---|
51.2.10 | [ADDED] Verify that the client is confidential and the authorization server requires the use of strong client authentication methods, i. e. 'mTLS' or 'private-key-jwt'. | β | ||
51.2.11 | [ADDED] Verify that the authorization server issues only sender-constrained (Proof-of-Posession) access tokens, either using mTLS certificate binding or Demonstration of Proof of Possession (DPoP). | β |
I am wondering if "strong client authentication method" would need be reworded to be more precise.
There are examples given, so it's not just an abstract "more precise". If there is better wording to propose, we can update.
There are examples given, so it's not just an abstract "more precise"
What I meant was: Should the main part of the sentence ("Verify that the client is confidential and the authorization server requires the use of strong client authentication methods") somehow describe what are the features of these authentication methods which makes them strong in order to motivate the intent behind the requirement.
I believe that important characteristics from the strong client authentication methods are that:
- they are resistant to replay attacks;
- the AS never has access to the client credentials (because they are based on public-key cryptography).
If we only consider (1) but not (2), then client_secret_jwt
would be considered as a strong client authentication method.
The intent of the proposed wording is to disallow client_secret_jwt
because this is not as safe as private_key_jwt
because the AS must have access to the shared secret to validate the JWT. This interpretation is consistent with draft-ietf-oauth-security-topics-24:
It is RECOMMENDED to use asymmetric (public-key based) methods for client authentication such as mTLS [RFC8705] or using signed JWTs ("Private Key JWT") in accordance with [RFC7521] and [RFC7523] (in [OpenID.Core] defined as the client authentication method private_key_jwt). When such methods for client authentication are used, authorization servers do not need to store sensitive symmetric keys, making these methods more robust against a number of attacks.
So I guess my question is: Is it clear enough in the current wording whether "strong client authentication method" would include methods based on a shared secret such as client_secret_jwt
? Or should we say something like:
[ADDED] Verify that the client is confidential and the authorization server requires the use of strong client authentication methods (based on public-key cryptography and resistant to replay attacks), i. e. 'mTLS' or 'private-key-jwt'.
I don't know answer for this. The logic here is simple - if you have a doubt, it should be fixed :) Also ping @TobiasAhnoff
Added via #2135
# | Description | L1 | L2 | L3 |
---|---|---|---|---|
51.2.10 | [ADDED] Verify that the client is confidential and the authorization server requires the use of strong client authentication methods (based on public-key cryptography and resistant to replay attacks), i. e. 'mTLS' or 'private-key-jwt'. | β | ||
51.2.11 | [ADDED] Verify that the authorization server issues only sender-constrained (Proof-of-Posession) access tokens, either using mTLS certificate binding or Demonstration of Proof of Possession (DPoP). | β |