When was the last time you connected an account you own with a third-party application or website? Have you ever used an app marketplace? Have you connected your GitHub account with another website? How many times have you been prompted to “allow access to” or “reauthorize” a connection? It happens so frequently that we barely notice it anymore. What is actually happening behind the scenes during this process? How can we as developers ensure we are safeguarding the applications we build and the people who use them? To start answering some of those questions, let's talk briefly about authorization.
Breaking down the authorization flow
If you recently hit an “Allow Access” button to enable an integration or update an existing app, you’ve likely initialized an authorization flow. The most popular authorization framework, where you are sharing information about your account with a third-party website or app, is known as OAuth 2.0. For example, at Jobber we have an App Marketplace where admin users are able to connect their Jobber accounts to third-party applications. Much like Facebook and Amazon, Jobber also uses OAuth 2.0 to facilitate third-party authorization. The Jobber admin user initiates a third-party app connection, grants requested permissions, and the user is directed to the app. The client request and subsequent authorization involves scopes, which specify and limit the information the third-party application will later be able to access.
But what is actually happening under the hood when you hit “Allow Access”? For an in-depth answer to that question, I suggest exploring the Authorization Code Grant documentation. To broadly summarize, once a user authorizes the client (a third-party website or app), the client receives an authorization code. The client can then redeem this authorization code for an access token and, possibly, a refresh token. The access token is short lived, provides access to the user's resources, and allows a client to make a request to retrieve data through an API. Just how short lived is an access token? This is determined by the authorization server that issues an access token with parameters such as
expires_in. When the access token inevitably expires, it can no longer be used to access user data or the API. Attempting to make an API request with an expired access token will result in a 401 Unauthorized error.
What does this mean for the user? If the authorization code grant only resulted in an access token, the user would have to start over and initiate the authorization flow once again. This wouldn’t be a great user experience, but remember that an access token provides access to sensitive information about the user. The longer an access token is valid, the more opportunity for a potential leak of user data. In certain cases, where security is paramount, having the user authorize a website or application for every visit or login could be by design. When it’s not the intended experience, how can developers ensure that a user has to authorize the client only once? Drumroll please. . . refresh tokens!
What are refresh tokens and why should we use them?
Refresh tokens are long-lived credentials that a third-party developer could use to request a new access token after it has expired. To redeem a refresh token, a third-party integration needs to authenticate itself. This is often done using a client identifier and client secret, which are essentially a username and password for the integration.
The ability to request for a ‘refreshed’ access token means that the user can remain logged in without repeating the authorization flow, providing a more seamless user experience. In addition, using a refresh token to request a new access token allows for the authorization server to issue very short-lived access tokens. Stored information should be short-lived whenever possible and an easy way to allow refresh tokens to also be short-lived, is through refresh token rotation.
How should we be using refresh tokens?
The specifics of how refresh token rotation is implemented can vary, but in general the rotation ensures that each time a refresh token is used to request a new access token, the authorization server will return a new access token as well as a new refresh token. When refresh tokens are being rendered invalid more frequently, the risk of replay attacks will decrease significantly.
Third-party developers who are building with Jobber’s Developer Center have the option to enable refresh token rotation. This feature can be selected while creating or when modifying an app. To provide a bit more context, when developers use a refresh token to request a new access token, they are using the following POST request:
POST /api/oauth/token HTTP/1.1 Host: api.getjobber.com Content-Type: application/x-www-form-urlencoded client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
The resources returned are, of course, the new access token and a refresh token. The refresh token will be either the same as before or new, depending on the client's rotation selection.
It is worth noting that there could be instances where the refresh tokens can expire. This may happen when a user has to re-authorize the client after a third-party developer adds additional scopes, or when the admin user chooses to disconnect from the client. This list of possibilities is not exhaustive, however it’s important to know that in cases such as these, the user will need to start the authorization process again if they wish to continue using the integration.
Let’s revisit the authorization flow once again through a Jobber lens:
- An admin user decides to connect to a third-party application through Jobber’s App Marketplace.
- The authorization flow begins once the Jobber admin user has been redirected to an authorization screen. In this authorization screen, the client is requesting authorization from the admin user who can in turn, approve the request by clicking “Allow Access”.
- The client receives an authorization code and then requests an access token and refresh token from the authorization server.
- The authorization server returns an access token and a refresh token.
- The access token expires after 60 minutes.
- If refresh token rotation is disabled, the refresh token is long-lived. For any subsequent redemption of a refresh token for an access token, the original refresh token is returned.
- If refresh token rotation is enabled, a completely new refresh token will be issued each time an access token is requested.
The frequency in which we take part in an authorization flow in our day-to-day lives is so high that rarely do we take a minute to ask ourselves, how does this integration actually work? I hope this article serves as a quick introduction into authorization and sparks your curiosity to dig deeper. I also hope that if you are a developer working on an app marketplace or building a third-party application, that you strongly consider utilizing refresh token rotation. Whenever possible, stored information should have a short lifetime and refresh token rotation is an easy way to improve the security of your applications.
Our awesome Jobber technology teams span across Payments, Infrastructure, AI/ML, Business Workflows & Communications. We work on cutting edge & modern tech stacks using React, React Native, Ruby on Rails, & GraphQL.
If you want to be a part of a collaborative work culture, help small home service businesses scale and create a positive impact on our communities, then visit our careers site to learn more!
Top comments (0)