Skip to content

Authentication scheme case-insensitivity #6228

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jgrandja opened this issue Dec 4, 2018 · 8 comments
Closed

Authentication scheme case-insensitivity #6228

jgrandja opened this issue Dec 4, 2018 · 8 comments
Assignees
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: declined A suggestion or change that we don't feel we should currently apply

Comments

@jgrandja
Copy link
Contributor

jgrandja commented Dec 4, 2018

/cc @vpavic @jzheaux @rwinch @tnwang @nlebas

Let's revisit the Authentication scheme case-insensitivity as it seems we're not all on the same page as of yet. This is related to #6150 #5586 #6195

I've re-read the 3 related specs and have provided references below along with my comments.

RFC 6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage

Key references

** Take note of the highlighted

2.1. Authorization Request Header Field

When sending the access token in the "Authorization" request header
field defined by HTTP/1.1 [RFC2617], the client uses the "Bearer"
authentication scheme to transmit the access token.

For example:

 GET /resource HTTP/1.1
 Host: server.example.com
 Authorization: Bearer mF_9.B5f-4.1JqM

The syntax of the "Authorization" header field for this scheme
follows the usage of the Basic scheme defined in Section 2 of
[RFC2617]
. Note that, as with Basic, it does not conform to the
generic syntax defined in Section 1.2 of [RFC2617] but is compatible
with the general authentication framework
being developed for
HTTP 1.1 [HTTP-AUTH], although it does not follow the preferred
practice outlined therein in order to reflect existing deployments.
The syntax for Bearer credentials is as follows:

 b64token    = 1*( ALPHA / DIGIT /
                   "-" / "." / "_" / "~" / "+" / "/" ) *"="
 credentials = "Bearer" 1*SP b64token

Clients SHOULD make authenticated requests with a bearer token using
the "Authorization" request header field with the "Bearer" HTTP
authorization scheme. Resource servers MUST support this method.

Comments:

  • Bearer scheme follows the usage of the Basic scheme defined in Section 2 RFC 2617
  • Basic scheme does not conform to the generic syntax defined in Section 1.2 of RFC 2617 (which is case-insensitivity for auth-scheme) but is compatible with the general authentication framework. The key point in the last sentence is COMPATIBILITY. So IMO, accepting a lower-case bearer or basic auth-scheme promotes this compatibility.

RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication

Key references

** Take note of the highlighted

1.2 Access Authentication Framework

HTTP provides a simple challenge-response authentication mechanism
that MAY be used by a server to challenge a client request and by a
client to provide authentication information. It uses an extensible,
case-insensitive token to identify the authentication scheme,
followed by a comma-separated list of attribute-value pairs which
carry the parameters necessary for achieving authentication via that
scheme.

2. Basic Authentication Scheme

The "basic" authentication scheme is based on the model that the
client must authenticate itself with a user-ID and a password for
each realm. The realm value should be considered an opaque string
which can only be compared for equality with other realms on that
server. The server will service the request only if it can validate
the user-ID and password for the protection space of the Request-URI.
There are no optional authentication parameters.

For Basic, the framework above is utilized as follows:

  challenge   = "Basic" realm
  credentials = "Basic" basic-credentials

Comments:

  • The challenge-response authentication mechanism explicitly states...it uses an extensible case-insensitive token to identify the authentication scheme. Therefore, the server MAY send back bearer or basic as the auth-scheme in the challenge as it is case-insensitive. Now given that the server may send back a case-insensitive auth-scheme, would it be logical to assume that the server may accept a case-insensitive auth-scheme in the client response as well? IMO, this makes sense and validates that auth-scheme is in fact case-insensitive on both ends.

RFC 7617 - The 'Basic' HTTP Authentication Scheme

Key references

** Take note of the highlighted

1. Introduction

This document defines the "Basic" Hypertext Transfer Protocol (HTTP)
authentication scheme, which transmits credentials as user-id/
password pairs, encoded using Base64 (HTTP authentication schemes are
defined in [RFC7235]).

This scheme is not considered to be a secure method of user
authentication unless used in conjunction with some external secure
system such as TLS (Transport Layer Security, [RFC5246]), as the
user-id and password are passed over the network as cleartext.

The "Basic" scheme previously was defined in Section 2 of [RFC2617].
This document updates the definition
, and also addresses
internationalization issues by introducing the 'charset'
authentication parameter (Section 2.1).

2. The 'Basic' Authentication Scheme

The Basic authentication scheme is based on the model that the client
needs to authenticate itself with a user-id and a password for each
protection space ("realm"). The realm value is a free-form string
that can only be compared for equality with other realms on that
server. The server will service the request only if it can validate
the user-id and password for the protection space applying to the
requested resource.

The Basic authentication scheme utilizes the Authentication Framework
as follows.

In challenges:

o The scheme name is "Basic".

o The authentication parameter 'realm' is REQUIRED ([RFC7235],
Section 2.2).

o The authentication parameter 'charset' is OPTIONAL (see
Section 2.1).

o No other authentication parameters are defined -- unknown
parameters MUST be ignored by recipients, and new parameters can
only be defined by revising this specification.

See also Section 4.1 of [RFC7235], which discusses the complexity of
parsing challenges properly.

Note that both scheme and parameter names are matched case-
insensitively.

For credentials, the "token68" syntax defined in Section 2.1 of
[RFC7235] is used. The value is computed based on user-id and
password as defined below.

Comments:

  • NOTE: RFC 7617 (this one) updates RFC2617.
  • This spec also states...both scheme and parameter names are matched case-
    insensitively.
    Although it refers to the auth-scheme in the challenge, IMO it should also support case-insensitivity in the client response (eg. Authorization header). It simply does not make sense if the server returns "basic" as the auth-scheme in the challenge and does not support "basic" in the client response Authorization header.
@jgrandja jgrandja added in: web An issue in web modules (web, webmvc) in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) labels Dec 4, 2018
@vpavic
Copy link
Contributor

vpavic commented Dec 13, 2018

I'm only going to address the Bearer part here, but it's really nothing outside of the thoughts I already expressed in my comments on #6150.

The section 2.1 of RFC 6750 is quite explicit on the syntax of Authorization header for Bearer authentication scheme. There's no ambiguity there that would warrant pulling other Authorization header related specs into the mix (for the Bearer part that is).

With the current situation, if one wants to build a fully spec compliant service (which behaves like Google's, for example) they need to provide a custom (?!) BearerTokenResolver implementation. And on the principal, it's hard for me to understand that the spec aligned default is being changed due to other parties that aren't fully spec aligned.

@jzheaux
Copy link
Contributor

jzheaux commented Dec 19, 2018

If the spec states that the scheme should be case insensitive, this should be our default, and then we should make it easy to deviate from that default.

The case for it being case-sensitive, as I see it, is here:

The syntax for Bearer credentials is as follows:

     b64token    = 1*( ALPHA / DIGIT /
                       "-" / "." / "_" / "~" / "+" / "/" ) *"="
     credentials = "Bearer" 1*SP b64token

This BNF doesn't leave room for case-insensitivity. And the spec doesn't make any comment to clarify.

The case for it being case-insensitive is that this paragraph:

The syntax of the "Authorization" header field for this scheme
*follows the usage of the Basic scheme* defined in Section 2 of
[RFC2617]. Note that, **as with Basic**, it does not conform to the
generic syntax defined in Section 1.2 of [RFC2617] but is compatible
with the general authentication framework

Implies that what is true for Basic is true for Bearer.

The syntax for Basic, from RFC2617 is:

credentials = "Basic" basic-credentials

But RFC2617 also says:

It uses an extensible, case-insensitive token to identify the authentication scheme

followed by:

auth-scheme = token

Placing these three statements together means that simply consulting the Bearer BNF isn't sufficient since the paragraph preceding the BNF clearly states that Bearer should be like Basic.

I do not see the same explicitness that @vpavic sees. Personally, if the paragraph didn't say "follows the usage of the Basic scheme" and "as with Basic", I would agree that we'd be left only with RFC 6750 to consult.

My conclusion is that the spec is unclear. Since it is unclear, Spring Security will likely be unsuccessful at stating that it defaults to case-sensitivity because it "follows the spec", implying that others do not.

Because the spec is ambiguous, then the next quality to look for is compatibility.

I don't have a lot to say about compatibility; @jgrandja mentioned to me offline that he was looking a bit into that, and we have anecdotes from members of the community that the components they use send bearer instead of Bearer.

However, a couple of quick points about the open-source authentication community:

  • Keycloak is case-insensitive for both Basic and Bearer authentication.
  • pac4j is case-sensitive for both Basic and Bearer authentication

I do not know whether pac4j's case-sensitivity is a proactive choice since it takes more thought to say equalsIgnoreCase than equals. However, with Keycloak it seems clear that a proactive decision was made to match the auth-scheme insensitively, and I would wager it was a compatibility choice.

Another point, then, is to consider consistency across Spring Security. BasicAuthenticationFilter allows for case-insensitivity, and so it is more surprising to the user to find out that we are case-insensitive there while being case-sensitive with bearer token authentication. If the spec were clear, I would advocate deviating from the pattern Spring Security already established. But since the spec is not clear on this point and since other frameworks and products are lenient on this point, Spring Security should be as well.

@jgrandja
Copy link
Contributor Author

I did a quick test with oauth2Login() to access the UserInfo Endpoint with (lowercase) bearer and this actually failed for Google and Okta. However, it did succeed for UAA. So there is definitely inconsistencies amongst different provider's.

@jgrandja
Copy link
Contributor Author

@rwinch @jzheaux @vpavic This issue has been open for quite some time. Can we close this or is there more to address?

@jgrandja jgrandja added status: waiting-for-feedback We need additional information before we can continue and removed in: web An issue in web modules (web, webmvc) labels May 18, 2021
@rwinch
Copy link
Member

rwinch commented May 18, 2021

Can we support strict case sensitivity and case insensitive environments?

@spring-projects-issues
Copy link

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label May 25, 2021
@jgrandja jgrandja removed status: feedback-reminder We've sent a reminder that we need additional information before we can continue status: waiting-for-feedback We need additional information before we can continue labels May 25, 2021
@jgrandja
Copy link
Contributor Author

@rwinch

Can we support strict case sensitivity and case insensitive environments?

Can you please elaborate so I can better understand.

@rwinch
Copy link
Member

rwinch commented May 26, 2021

We spoke about this offline and determined this is completed.

@rwinch rwinch closed this as completed May 26, 2021
@rwinch rwinch self-assigned this May 26, 2021
@rwinch rwinch added the status: declined A suggestion or change that we don't feel we should currently apply label May 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

5 participants