I got the opportunity to integrate bearer token authentication into our system. As I started working on this task, I did some research to understand the basic concepts and workflow.
I find it challenging to understand all the necessary details as the information is scattered on the internet.
This story documents all my research in one place to facilitate my audience.
An access token is a bearer token used to access protected resources (see Figure 1). However, a client obtains an access token by providing valid credentials.
For security reasons, an access token is short-lived.
I used 15 minutes lifespan for an access token.
A refresh token is not a bearer token but simply a random string. It means refresh tokens are not for accessing protected resources.
When an access token expires, a refresh token is used to obtain a new access token. Figure 1 above illustrates this concept.
Typically, a refresh token is long-lived.
I used a 1-week lifespan for a refresh token.
I followed this guide  for the basic workflow.
- The client requests an access token by providing valid credentials.
- Auth server authenticates the credentials and issues an access token & a refresh token.
- The client requests to access a protected resource by providing the access token.
- The resource server serves the request upon a valid access token.
- Steps (3) and (4) require a valid access token. If the client’s access token is expired, it skips to step (7); otherwise, it sends a request to access another protected resource.
- Since the access token has expired, the resource server forbids accessing protected resources and returns an invalid token error.
- The client requests a new access token by submitting the refresh token.
- Auth server validates the refresh token and issues a new access token & new refresh token.
Representation of access and refresh token
As mentioned before, a refresh token is simply a random string. However, an access token has a specific representation. As per RFC 
Access tokens can have different formats, structures, and methods of utilization (e.g., cryptographic properties) based on the resource server security requirements.
I used JSON Web Token (JWT)  format for an access token. As per this article 
a well-formed JWT consists of three concatenated Base64url-encoded strings, separated by dots (.)
Example JSON Web Token (JWT) generated online via https://jwt.io/ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV\_adQssw5c
You can read more about this format here .
Why JWT format?
This JWT format allows us to validate an access token without DB lookup. It means
we don’t have to store the access token in our DB for validation purposes.
That’s the beauty of this format.
Libraries supporting JWT implementation
You may find plenty of libraries supporting JWT implementation, but I recommend using this library  if you use Scala. Reasons?
- Good documentation
- Actively contributed (commits: ~850, version: 9.x.x)
Security of refresh token
As refresh tokens are long-lived and are used to obtain an access token, it is crucial to keep them secure. To this end, refresh tokens are rotated .
So, every time a client exchanges a refresh token to get a new access token, a new refresh token is also returned (see Figure 1). It means:
the old refresh token is no longer valid and cannot be used to retrieve a new access token.
As refresh tokens are continually exchanged and invalidated, this reduces the threat of unauthorized access to our protected resources.
Furthermore, these refresh tokens are stored in the DB so that they can be revoked anytime (if needed).
Thanks for reading.
Originally written on medium