pwshub.com

The Curious “Case” of the Bearer Scheme

Specifications aim to find a common way to interoperate. This is why they need to be precise and unambiguous. But sometimes wrong interpretations occur, leading to implementations that break that desired interoperability. The “case” of the bearer scheme in OAuth 2.0 is one of these situations.

The Problem with the Bearer Scheme

Imagine your application is calling a protected third-party API and getting an error you don’t understand. Everything worked fine in your test environment when you mocked the API. Why does it fail when you call the actual API? This happens many times, but you have checked everything this time, and your code looks fine. You are passing an access token, which you are sure is valid and not expired. Yet you still have that 500 - Internal Server Error as response status code or, if you're lucky, 401 - Unauthorized.

After hours of investigations, you find that you were using “bearer” as the string that qualifies the scheme of your access token while the API expects “Bearer”. That's to say, your HTTP request is like the following:

GET /shop/orders
Host: api.example.com
Authorization: bearer eyJhbGciOiJIUzI1...

But the API expects a request like this:

GET /shop/orders
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1...

The letter case of "b" in "bearer" is the only difference! 😳

You can’t change the third-party API, of course, so you need to change your application. Is it fair?

The Discussion on the Bearer Scheme Case

You may think that the situation described in the previous section is an exceptional case. Actually, it's more common than you think (see this, this, this, and this, just for a few public examples).

There are many discussions about the correct letter case of the bearer scheme identifier in OAuth 2.0. Some say it should be capitalized, while others say it should be case-insensitive. Someone turned from case-insensitive to capitalized just to honor the specifications, not because they had any issue ( here and here, for example).

Many argue that the first letter should be capitalized and mention the specifications:

The syntax for Bearer credentials is as follows:
     b64token    = 1*( ALPHA / DIGIT /
                       "-" / "." / "_" / "~" / "+" / "/" ) *"="
     credentials = "Bearer" 1*SP b64token

Others claim that it should be case-insensitive and mention the specifications as well:

token_type
         REQUIRED.  The type of the token issued as described in
         Section 7.1.  Value is case insensitive.

It sounds like a philosophical discussion, but it has practical consequences. Who is right?

Solving the Bearer Scheme Case

The OAuth 2.0 specifications clearly state that the token type (i.e., the "bearer" string) must be case insensitive. However, the syntax defined in the Bearer Token Usage specifications seems to contradict what the other one established. The ABNF expression defining the syntax uses "Bearer", the capitalized version:

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

Apparently the specifications seem inconsistent. 🤔

However, according to the specifications of the ABNF grammar:

NOTE:
      ABNF strings are case insensitive and the character set for these
      strings is US-ASCII.
   Hence:
         rulename = "abc"
   and:
         rulename = "aBc"
   will match "abc", "Abc", "aBc", "abC", "ABc", "aBC", "AbC", and
   "ABC".
   To specify a rule that is case sensitive, specify the characters
   individually.
   For example:
         rulename    =  %d97 %d98 %d99
   or
         rulename    =  %d97.98.99
   will match only the string that comprises only the lowercase
   characters, abc.

That means that the case-insensitive party is right! 🎉

You can write the "bearer" keyword however you like. This is more of a warning to API implementers than client builders because to be truly OAuth 2.0 compliant, they MUST accept any form of "bearer" keyword.

To remove any doubt, the OAuth discussion group added a note to the upcoming OAuth 2.1 specifications:

As described in Section 2.3 of [RFC5234], the string Bearer is case-insensitive. This means all of the following are valid uses of the Authorization header:
Authorization: Bearer mF_9.B5f-4.1JqM
Authorization: bearer mF_9.B5f-4.1JqM
Authorization: BEARER mF_9.B5f-4.1JqM

Keep in mind that even auThoriZation: bEAReR mF_9.B5f-4.1JqM must be accepted. The HTTP header field names are case-insensitive, too. 😜

Conclusion

Small details that may seem insignificant can sometimes create incompatibility problems, and it may take a lot of time to figure out what's going on and find the correct solution. Writing (and reading) protocol specifications is complex. You must avoid ambiguities in their drafting and have a good technical background to read and implement them correctly.

I hope that this brief digression into the details of the OAuth specifications will be helpful to you and save you hours of debugging when an API is a little reluctant to accept creative ways of writing "bearer". 😇

Source: auth0.com

Related stories
3 weeks ago - Earlier this month, I discussed how Chrome's upcoming built-in AI support was adding new features specifically tailored to certain use-cases. In that post, I looked at the Summarizer API. For today, I decided to take a look at the...
1 month ago - This year, the React team unveiled something they've been quietly researching for years: an official way to run React components exclusively on the server. This is a significant paradigm shift, and it's caused a whole lot of confusion in...
1 month ago - Get a sneak peek at the upcoming features in Python 3.13 aimed at enhancing performance. In this tutorial, you'll make a custom Python build with Docker to enable free threading and an experimental JIT compiler. Along the way, you'll...
1 month ago - In our community, it's so common for developer projects to be open-source. I'm breaking with this trend for my blog, but I have good reasons! In this article, I'll share my reasoning, as well as a workaround in case you _really_ want to...
1 month ago - “Margin collapse” has a dastardly reputation, one of the trickier parts of CSS. Fortunately, it gets a lot easier once you learn a few rules! In this tutorial, we take a deep dive into the governing principles, and learn how to use them...
Other stories
26 minutes ago - Fixes 41 bugs (addressing 595 👍). node:http2 server and gRPC server support, ca and cafile support in bun install, Bun.inspect.table, bun build --drop, iterable SQLite queries, iterator helpers, Promise.try, Buffer.copyBytesFrom, and...
4 hours ago - This guide provides a foundational understanding of Redux and why you should use it for state management in a React app. The post Understanding Redux: A tutorial with examples appeared first on LogRocket Blog.
6 hours ago - Discover some of the best Node.js web scraping libraries, including Axios and Superagent, and techniques for how to use them. The post The best Node.js web scrapers for your use case appeared first on LogRocket Blog.
9 hours ago - Infinite runner games have been a favorite for gamers and developers alike due to their fast-paced action and replayability. These games often feature engaging mechanics like endless levels, smooth character movement, and dynamic...
12 hours ago - Yesterday, Elizabeth Siegle, a developer advocate for CLoudflare, showed off a really freaking cool demo making use of Cloudflare's Workers AI support. Her demo made use of WNBA stats to create a beautiful dashboard that's then enhanced...