The Grand Identity Unification
Nelson Parente, Software Engineer
In my first article for the F-Tech Blog, Authorization and Authentication @ FARFETCH, we covered core concepts of Identity and how these concepts evolved and are handled at FARFETCH.
We understood the difference between Authentication, “who are you?”, and Authorization, “what can you do?”, understood the importance of the OAuth, OpenIDConnect protocols, it’s major terminologies, and how all these concepts connect together.
In May 2020, FARFETCH gave us the opportunity to participate in a full day workshop with Dominick Baier, one of the founders of IdentityServer. In this workshop, Advanced OAuth, we covered several topics regarding authorization, authentication, and application security. Among the topics presented in the workshop was the new OAuth 2.1 specification.
If you recall my latest article, that article made an introduction to the Authorization protocol, OAuth 2.0. This article will be focused on the last evolution of this protocol specification OAuth 2.1.
The FARFETCH platform is enhanced and expanded every day, in the same way that our Platform evolved, so did the OAuth 2.0 protocol specification. The protocols used for Authorization and Authentication specifications are updated, bringing with it new concepts and the deprecation of some old ones. Therefore the FARFETCH ID Cluster needs to be constantly up to date with these changes so that our Platform can be up to date with the latest best practices of these protocols.
The OAuth 2.0 protocol specification evolved into OAuth 2.1 and one of the biggest changes that came with this evolution, is what some people call the Grand Unification.
The Grand Unification is a best practice intended to help with choosing the right grant type for an application. Choosing the right grant type for an application is crucial to ensure the security of it. At FARFETCH, the security of our two million consumers and hundreds of applications is a top priority, therefore these guidelines have the utmost importance.
First, let’s remember what is a grant type and which grant types are contemplated in the OAuth 2.0 protocol.
OAuth 2.0 Grant Types
A grant type is a method through which an application can get an Access token which grants it access to limited resources. OAuth 2.0 defines and supports multiple grant types.
In the OAuth 2.0 specification, these grant types allow different kinds of authorization and have their own specifications and details. This means that depending on the application use-case some are better suited than others.
OAuth 2.1 specification
The OAuth 2.1 specification brings some new exciting changes to the protocol. This isn’t a new protocol, it is an ongoing update to consolidate and simplify the most used features in OAuth 2.0.
Among other important changes, there are some that are specific to grant types. The OAuth 2.1 specification includes the omission of the Implicit grant type, the deprecation of Resource Owner Password Credentials (ROPC), the mandatory use of proof key for code exchange (PKCE) with the Authorization Code grant type, and the omission of the bearer token usage in query string parameters.
This may sound like jargon to those who aren’t so familiar with these concepts, but in fact, these changes are very straightforward and easy to understand why they took place. So let us break down these changes:
- The Resource Owner Password Credentials(ROPC) grant type is deprecated;
- The Implicit grant type is omitted from the specification;
- PKCE is the default for Authorization Code grant type;
Now you’re probably wondering why these changes took place. That’s a great question!
The grant type Resource Owner Password Credentials was added in the OAuth 2.0 specification in order to ease the migration to OAuth for legacy systems and was now deprecated and shouldn’t be used anymore. At this moment there are more suitable options to cover the original use cases of ROPC. The main issue with this grant type is the need to send the username/password combination from an environment outside the IdentityProvider, for example, a mobile application.
The Implicit grant type was introduced in 2012 as a workaround to overcome cross-origin AJAX limitations but this was later solved with CORS. Still, this grant type wasn’t deprecated in the OAuth 2.1 specification but it was omitted.
The Implicit grant type is natively insecure when used, for example, in Single Page Applications because the access token is returned in the response URL. Since access tokens are not one-time-only and depending on the client configuration, these can live up to several days and be intercepted and used maliciously.
The main difference between the deprecation of ROPC and the Implicit grant type is that the specification says that the Implicit grant type shouldn’t be used, however, if one wishes to do so, it can still be used as long as the Identity Provider has a way to prevent the access token injection. Nevertheless, in the end, there are more secure options like Authorization Code + PKCE.
PKCE stands for ‘proof key for code exchange’ and it’s an extension to the Authorization Code grant type that was explained in my first article. This extension adds an extra layer of security that ensures that when exchanging the code for an access token, no interception or modification is made. We’ll look deeper into this later in this article.
The changes in the OAuth 2.1 specification lead us to the Grand Unification. This isn’t written in the specification, but it is taken as a best practice as presented to us by Dominick Baier, one of the most active people in the OAuth world.
The Grand Unification
When we talk about authorizing applications and authenticating users, we divide the applications that handle these into public and confidential applications.
- Public: Public applications are unable to maintain the confidentiality of their credentials, such as single-page applications, mobile, and native applications because these live on the client-side;
- Confidential: Confidential applications are capable of maintaining the confidentiality of their credentials, such as an application hosted in a secure server;
In order to ensure the confidentiality of the credentials, applications need to be kept in a safe place where they cannot be exploited. For example, imagine that we store a client’s secret in the source code of a mobile application, that application will be installed in a smartphone and is prone to reverse-engineering in its binary files and therefore leaking the credentials that the application uses for authentication.
The ability to maintain confidentiality is a key aspect when securing an application with the right grant type. However, there is another very important condition that should be taken into consideration and this is the one condition that this Grand Unification is based on. We can categorize the authorization process of an application into two categories: interactive and machine-to-machine. This division is made by considering the need of having some sort of interaction with an external entity other than the IdentityProvider, in order to complete the authorization process.
- Interactive: We can consider an application Interactive when it needs to interact with another entity, e.g. user credentials input in the browser, in order to complete the authorization process. This is a very common case within client-side applications;
- Machine-to-Machine(M2M): These applications can complete their authorization process interacting only with the IdentityProvider and the Token endpoint, typically these applications are hosted in a secure server-side;
The Grant Type Unification is based upon these two categories and the applications specific authorization requirements. When an application needs to have any sort of interaction to complete the authorization process, it should use Authorization Code + PKCE grant type ( RFC 7636). Otherwise, applications able to do the authorization process should use the Client Credentials grant type ( RFC 6749). Please be mindful that this unification covers the most common use cases, it isn’t valid for very specific use cases, e.g. authorizing IoT devices.
Authorization Code + PKCE
The Authorization Code + PKCE is an extension to the already existing authorization code flow, this extension adds the PKCE.
It brings an extra layer of security, mitigating some well-known attacks like the “Man-in-the-middle”. In this type of attack, if a client secret is exposed and the authorization code is intercepted by a malicious entity, it is possible that said entity could be able to retrieve an access token on behalf of a legitimate application.
Before going deeper into the flow let’s break it down, into smaller shinier pieces:
- Code Verifier: high-entropy cryptographic STRING;
- Code Challenge: Transformation from the Code Verifier using in preference SHA256 and Base64 encoding;
- Code Challenge Method: The Code Challenge transformation method, can be SHA256 or plain in the case of no transformation due to technology limitations;
The flow is very similar to the Authorization Code with extra sparks that make a big difference.
- The Resource Owner wants to allow the Client Application to access its addresses.
Before initiating the authorization request the client application creates a Code Verifier and derives it into the Code Challenge.
- The Client Application redirects the browser to the Authorization Server and includes with the request the Client ID, Redirect URI, Response Type, one or more Scopes, and the Code Challenge it needs.
- The Authorization Server verifies who the Resource Owner is, and, if necessary, prompts for a login.
- The Authorization Server stores the Code Challenge and redirects back to Client Application using the Redirect URI along with an Authorization Code.
- The Client contacts the Authorization Server directly (not using the Resource Owner’s browser) and securely sends its Client ID, Client Secret, the Authorization Code, and the Code Verifier.
- The Authorization Server verifies the data and transforms the Code Verifier received to see if it matches with the Code Challenge received initially. If everything is valid, respond with the Access Token.
- The Client can now use the Access Token to send requests to the Resource Server for its addresses.
The diagram below represents the flow of the Client Credentials grant type that is the recommended grant type for M2M authorization.
This flow is very short and simple, since both the application and the IdentityProvider are in a trustworthy environment. So let’s break down each step of this flow:
- Application calls the IdentityProvider Token endpoint with its Id, Secret and the requested scopes;
- The IdentityProvider validates the request and returns an access token;
- The application can now call another API with the Token in order to get data;
Evolving with Kindness
At FARFETCH, the security of our customers, partners and applications is a top priority. The concepts mentioned above are crucial to strengthen our Platform.
Nevertheless, these kinds of changes cannot be done overnight since they involve lots of different teams, each with their own roadmaps and priorities, so we need to coordinate and work collectively in order to adapt and evolve our platform to the current best practices for these specifications.
Our Security team has a major role in ensuring applications follow best practices.
In order to adapt to these new changes and concepts, we follow some golden rules and always take actions aiming to make the process as smooth and easy as possible for all the people involved. We must also ensure current contracts do not break. This is a short but strong rule.
They can however be deprecated, meaning, from now on no one can use them again.
This kind of evolution is always a big challenge when done at scale. At FARFETCH, we have hundreds of different applications and each day our FARFETCH Platform grows more and more. Therefore we must be careful when configuring authorization for new applications, we must follow the best standards and practices because each application created that doesn’t follow the current best practices will have to be worked on in the future.
Finally, I cannot stress enough how important it is to have well-written documentation that accurately answers all the questions. Documenting the knowledge we have is the best way to pass it around the company and through multiple teams, this documentation should be written in a clear and easy to understand manner and should be always kept up to date.
Wrapping it up, the FARFETCH ID Cluster works every day to ensure the security of our customers, partners and applications. We take this mission very seriously and we make sure we are following the industry best standards and practices. Therefore, it is of the utmost importance to stay up-to-date with the latest updates to the OAuth 2.1 specification.
The FARFETCH Platform is growing every day, and with this growth, new challenges arise when structural changes must be done. Our end goal is to have the highest level of security in our platform and the Grand Identity Unification brings us closer to that goal.
Originally published at https://www.farfetchtechblog.com on March 5, 2021.