Keep Client Credentials Secure
Pattern |
Only issue client secrets to “confidential clients,” and store them like you’d store any sensitive API keys. |
Anti-Pattern
|
Putting client secrets in a single-page app or mobile app
|
When you first register an app at the OAuth server, you’ll get a client ID to identify the app, and you may also get a client secret used to authenticate the app. This client secret is effectively the application’s password, and you need to treat it as such. That means making sure it’s kept secure, only sent to the authorization server, and never shared with anyone.
Only certain types of applications have this ability and are known as “confidential clients” in OAuth terms. The most common example of a confidential client is one that runs server-side code (e.g., .NET, Java), where the code on the server can be configured with this client secret, and the secret won’t be visible to users of the application.
On the other hand, “public clients” are applications that don’t have the ability to keep a secret secure, so they aren’t given a client secret in the first place. The most common example of public clients are mobile apps and single-page apps. If you included a client secret in a single-page app, anyone who uses the app would first download the JavaScript code, including the secret, which would then be visible to anyone using the app. These kinds of apps can’t keep secrets secure, so instead, we use an OAuth flow that doesn’t require a secret at all.
Use PKCE Instead of Implicit Flow
Pattern |
Use the Authorization Code flow with PKCE for public and confidential clients.
|
Anti-Pattern |
Using the Implicit flow to get access tokens
|
The Implicit flow in OAuth 2.0 was created over 10 years ago when browsers worked very differently than they do today. The primary reason the Implicit flow was created was because of an old limitation in browsers that prevented them from making cross-domain requests.
The standard OAuth Authorization Code flow requires that a POST
request is made to the OAuth server’s token endpoint. In the past, if the token endpoint was on a different domain than the app, JavaScript would be unable to make this request due to cross-origin limitations. The Implicit flow worked around this limitation by avoiding the POST
request, and instead, returning the access token immediately in the redirect, as shown in the figure below:
Figure 1: OAuth Implicit flow
Working around the browser limitations came with the tradeoff of this flow being inherently less secure. The problem is that the access token is delivered to the client through the front channel (the browser redirect), rather than the client retrieving it from the authorization server itself via the back channel. For a more in-depth analysis of the risks, please visit oauth.net/implicit.
Modern browsers no longer have these old limitations, and we can now use the more secure Authorization Code flow from the browser itself. In order to secure this flow without a client secret, we use a mechanism known as PKCE.
Figure 2: OAuth Authorization Code flow
In the PKCE model, the only data going through the less secure front channel is the temporary authorization code rather than the access token itself. The client first generates a PKCE Code Verifier when it starts the request and uses it when exchanging the authorization code for an access token in the second part of the flow. The access token is delivered via the back channel where it can be protected and kept secure in transit.
In short, there isn’t any need for the Implicit flow anymore, and it will be removed in a future update of the OAuth specification. The Authorization Code flow with PKCE provides better security and is the best option to use in place of the Implicit flow.
This is a preview of the OAuth Patterns and Anti-Patterns Refcard. To read the entire Refcard, please download the PDF from the link above.
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}