If you’re like me, you may have heard how OAuth 2.0 is the industry standard, and any modern app should be using it for authentication and authorization. Maybe you also wondered how all of these apps support single sign-on through Google, Microsoft, or Twitter, allowing users to reuse their existing social media accounts to create an account for your app, thereby outsourcing the risks of “rolling out your own security” to a well-trusted third party and not pestering users with yet another set of login credentials.
The aim of this article is to demystify OAuth 2.0 and OpenID Connect, why they are more secure than traditional methods, and how you can start using them today. While there are many details to be explored, this article is only intended to be an introduction.
What is OAuth 2.0?
OAuth 2.0 is an open standard for authorization. The reason for its existence is to allow users to grant access to their private data from one service provider (the resource server) to another (the client application). In this process, only an authorization server ever handles user credentials – client apps do not touch the user’s password nor do they know their identity. Instead, OAuth 2.0 leverages HTTP and redirect URIs to first authenticate users directly with the authorization server, which in turn responds back an authorization grant to the client application via a HTTP redirect. The client then follows one of several flows to exchange the grant for an access token. Finally, this access token can be used by the client to retrieve the user’s private data from the resource server, all without ever sharing the user’s password across sites.
For example, if you’ve ever used TurboTax, you’ll be asked to sign-in to various bank or loan accounts to import your financial data. TurboTax only needs authorization from you to acquire this information, so to be secure, you will sign-in directly to your bank (usually from a browser popup), and grant access. You are then redirected back to TurboTax. TurboTax is never given your password. What TurboTax is given, however, is a temporary access token by your bank. This token allows TurboTax, without knowing your identity or password, to pull the needed financial information.
In OAuth 2.0, you’ll encounter grant types and public vs. confidential clients. The grant type defines which flow is used to acquire an access token, and the client type describes whether or not the user can see the access token and whether the client is configured with a “client secret”. The grant type and client type have different security implications. If the client is a web app, then the client is considered confidential since the user never sees the access token issued by the authorization server. Public clients on the other hand refer to any app that is distributed to end-users such as single-page applications, desktop, or mobile apps. These are apps the user downloads (and can potentially decompile) and must use the access token to retrieve protected data. For this reason, an additional security measure known as PKCE (Proof Key for Code Exchange) is required to ensure that the authorization grant (and therefore the access token) are not intercepted. You may have different needs, but the recommended OAuth flow is to use the Authorization Code grant type with the PKCE extension, irrespective of whether or not the client is public or confidential – it turns out that there are some less common scenarios where PKCE provides a defense even for confidential clients.
Security Problems Addressed by OAuth 2.0
In a traditional authorization setup, third-party apps like TurboTax would need to access your credentials for the initial data retrieval and it would need to store them for subsequent requests. This is a huge security issue! What if TurboTax were compromised? Should they be trusted to the same degree as the bank? If compromised, not only would attackers know your bank password, but possibly your password for other online services. And previous passwords can also help attackers recover accounts too! Do I need to say how common it is for users to reuse their password, in part or whole?
Furthermore, should we just trust TurboTax to only read your bank information? Handing them a password gives them full access and could very well allow TurboTax to initiate transfers.
So instead of password sharing, OAuth 2.0 prescribes the use of access tokens as an abstraction layer to replace traditional authorization methods. Access tokens are safer to transmit over the internet, they can be scoped to reduce the level of access of private information, they can be set to expire, and they are safer to persist. And if users want, they can be revoked easily by making a request to the authorization server. There is no need to change your password, which would have traditionally revoked access for all third-party apps.
What is OpenID Connect?
OpenID Connect (OIDC) is an authentication layer built on top of OAuth 2.0 and enables single sign-on (SSO). While OAuth 2.0 is strictly concerned about authorizing access to protected resources, this layer adds a standard to authenticate and identify a user.
OIDC allows client apps (called Relying Parties or RPs in the context of OIDC) to identify users based on the authentication performed by an authorization server (also known as an OpenID Provider or OP).
In OIDC, the authorization flow is the same, with the exception that in addition to returning an access token, the OpenID provider also returns an ID token. The ID token is a JSON web token (JWT) that includes claims about the user’s identity. Specifically, the token includes a subject identifier, which is a locally unique string used by the OpenID provider. The subject identifier can be used to support single sign-on and your app can associate it with app-specific resources the user owns. You may even wish to persist the identities returned by multiple OpenID providers to link accounts and allow multiple sign-ins.
Getting Started with Single Sign-On
While this article is just an introduction to the topic, I want to conclude with a few pointers to get started implementing single sign-on. As far as I know, single sign-on can be enabled without OpenID, but this relies on proprietary protocols instead of an open standard. Please refer to this list on Wikipedia to see which companies are OAuth 2.0 or OpenID providers. All this means is that supporting single sign-on through some providers may require extra work and could have different security implications.
When I was experimenting with single sign-on for a Flutter app I am working on, I found very fast success using both Google Firebase Auth and Azure Active Directory B2C. Both platforms allow you to enable SSO for prominent identity providers such as Microsoft, Google, Apple, Twitter, and Facebook. Also for both platforms, the setup was about the same. I needed to create an app registration to generate a client ID & secret and to tell the OpenID provider which permissions my app was interested in. Also, I was able to provide the redirect URIs that are returned upon successful user authentication. The URI scheme will vary based on who is responding to it. For instance, I at first used azure_ad_authentication, a small Flutter wrapper for the Microsoft Authentication Library (MSAL). When doing so, the URI needed to be configured for allowing redirection to my Flutter app. On iOS, this took the form:
To use this redirect, I needed to modify my Info.plist to accept the URI scheme
msauth.$(BUNDLE_ID) so iOS would launch my app when processing the redirect. I eventually switched over to use Firebase since there is significantly more support for it on Flutter. As a result, Firebase was now responsible for sending the redirect to my app. But, for Firebase to delegate authentication to Microsoft, I needed to supply my Firebase project’s application secret and redirect URI to Azure AD. So, the URI for Azure AD changed to take the form:
Both scenarios worked great; I was able to sign in using Microsoft Accounts directly though MSAL, and indirectly through Firebase. Plus, there is a whole host of options to support SSO through other providers with Firebase, as well as traditional e-mail & password authentication and even anonymous authentication.
To learn more about OAuth 2.0 and OpenID, I highly recommend reviewing the official RFCs and sites. There is a wealth of information and history that further explain the options and security considerations:
I also found some great articles that explain the importance of PKCE, even when using confidential clients: