What Does The ‘Authorization: Bearer xxx-yyy-zzz’ Header Mean?

That’s right, it’s something to do with OAuth2.0!

James Collerton
4 min readJan 14, 2023
A bear-er of tokens (it’s hard to find pictures for abstract concepts!)

Audience

In this article we will explain the usage of the Authorization: Bearer xxx-yyy-zzz style header. I feel it’s one of those things that you might use a fair bit without perhaps fully understanding the implications.

This article is a crash course in understanding where it comes from, how it works and when to use it. It is based on the RFC here, which you can read for full technical details.

It expects an understanding of HTTP and OAuth2.0. Although I will offer a brief overview of the latter, I would recommend reading my introductory article here.

Argument

The Basics

OAuth2.0 is about authorisation, not authentication. That is, it cares about what we can do, not who we are.

The core of OAuth2.0 is that there is a resource server which holds resources we want. We need a key we can present to a resource server that it can check is valid in order to give us access.

The way we represent this key is using an access token. This access token contains all of the information on what we can do (but not who we are). It’s exactly like a door key — it doesn’t matter who has it, as long as it fits the lock we’re allowed in!

Access to our resource server is done using HTTP. The Authorization: Bearer header is used to send this key along with our request to the resource server.

This is an example of an HTTP Authentication Scheme. Other examples could be basic, which would use an Authorization: Basic header.

The bearer bit is key (pun intended). Anyone who has (bears) the token can use it, therefore we need to take care to keep it securely!

Note, how to get an access token is covered in the article here, with more details in the list of articles here, and is beyond the scope of this piece. For this article just assume we have one.

The Implementation

Now we understand conceptually, let’s look at what this means in reality.

The first important thing is we must use TLS. A typical request to a resource server for a protected resource would then look something like:

GET /protected-resource HTTP/1.1
Host: resourceserver.example.com
Authorization: Bearer access_token

In short, we send an authorization header with value Bearer, a space, then the access token.

If we’re making a POST request we could also send the access token in the method body, using the below syntax:

POST /protected-resource HTTP/1.1
Host: resourceserver.example.com
Content-Type: application/x-www-form-urlencoded

access_token=access_token_value

And finally we can also use the query params to specify the token:

https://server.example.com/resource?access_token=access_token_value

We can see why it’s so important to use TLS. By doing this we guarantee that each of the above is encrypted, and only the resource server can read our access token.

So far, so good. We’re defining a way of sending over a token. However, what happens when we forget or it isn’t valid? We need a server error response!

Let’s say we’ve got an access token, but it doesn’t have the right scopes (i.e. we have some permissions, but not for the resource we’re asking for). In this case we’ve not got access to The Beatles’ explicit tracks.

Then we may get a response similar to the below:

HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer realm="examplerealm",
error="insufficient_scope",
scope="urn:example:artist=TheBeatles&urn:example:age=O18"
error_description="Cannot access tracks!"

We see we return a sensible error code, then use the WWW-Authenticate header to prompt for authentication.

We specify the HTTP Authentication scheme (bearer), then at least one other auth-param value. These can include:

  • The realm: If we have multiple resources on a resource server, each of which need their own different types of protection we may separate them into ‘realms’. This allows us to group them according to their protection needs.
  • The scope: This is a list of scopes that are required to access the resource.
  • The error: one of the linked values explaining what the issue was.
  • The error_description: A human readable error message that can be displayed to end users.
  • The error_uri: A link to a human web page explaining the error.

With all of this information, it is then the responsibility of the user to go away and get the required access token!

Conclusion

And there you have it! What that header means, how we use it, and how we deal with responses!

--

--

James Collerton

Senior Software Engineer at Spotify, Ex-Principal Engineer at the BBC