OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
In OpenID Connect, OAuth 2.0 capabilities are integrated with the protocol itself.
OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 is NOT an authentication protocol.
Authentication is the process of verifying who you are. When you log on to a PC with a user name and password you are authenticating. I disagree with this definition of authentication. If an attacker is able to obtain my user name and password and is able to log on the associated system, it does not mean the system authenticated me. Authorization is the process of verifying that you have access to something. Gaining access to a resource (e.g. directory on a hard disk) because the permissions configured on it allow you access is authorization.
Bruce Schneier spent a chapter on Identity, Authentication, and Authorization in his book Beyond Fear Thinking Sensibly about Security in an Uncertain World, September 2003, Copernicus Books (296 Pages). I looked for a copy in my paper library but seem I am not able to locate it. After further attempts, decided to check on Amazon.com. Apparently I might not have purchased this book. In order to resolve the issue, I used my Prime membership to order a fresh copy. Should receive the book this Thursday :o) I am quite interested in finding out his opinion on the subject.
OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices.
What is authentication? Authentication in the context of a user accessing an application tells an application who the current user is and whether or not they’re present. A full authentication protocol will probably also tell you a number of attributes about this user, such as a unique identifier, an email address, and what to call them when the application says “Good Morning”. Authentication is all about the user and their presence with the application, and an internet-scale authentication protocol needs to be able to do this across network and security boundaries.
However, OAuth tells the application none of that. OAuth says absolutely nothing about the user, nor does it say how the user proved their presence or even if they’re still there. As far as an OAuth client is concerned, it asked for a token, got a token, and eventually used that token to access some API. It doesn’t know anything about who authorized the application or if there was even a user there at all. In fact, much of the point of OAuth is about giving this delegated access for use in situations where the user is not present on the connection between the client and the resource being accessed. This is great for client authorization, but it’s really bad for authentication where the whole point is figuring out if the user is there or not (and who they are).
As an additional confounder to our topic, an OAuth process does usually include several kinds of authentication in its process: the resource owner authenticates to the authorization server in the authorization step, the client authenticates to the authorization server in the token endpoint, and there may be others. The existence of these authentication events within the OAuth protocol does not translate to the OAuth protocol itself being able to reliably convey authentication.
As it turns out, though, there are a handful of things that can be used along with OAuth to create an authentication and identity protocol on top of this delegation and authorization protocol. In nearly all of these cases, the core functionality of OAuth remains intact, and what’s happening is that the user is delegating access to their identity to the application they’re trying to log in to. The client application then becomes a consumer of the identity API, thereby finding out who authorized the client in the first place. One major benefit of building authentication on top of authorization in this way is that it allows for management of end-user consent, which is very important in cross-domain identity federation at internet scale. Another important benefit is that the user can delegate access to other protected APIs alongside their identity at the same time, making it much simpler for both application developers and end users to manage. With one call, an application can find out if a user is logged in, what the app should call the user, download photos for printing, and post updates to their message stream. This simplicity is very compelling, but by doing both at the same time, many developers conflate the two functions.
Authentication vs. Authorization: a metaphor To help clear things up, it may be helpful to think of the problem in terms of a metaphor: chocolate vs. fudge. Vittorio Bertocci in his post OAuth 2.0 and Sign-In provides detail on the security boundaries between parties and why the authorization layer makes sense as the lower layer to build on top of, and provides the source of the chocolate-vs-fudge metaphor here referenced.
OAuth, in this metaphor, is chocolate. It’s a versatile ingredient that is fundamental to a number of different things and can even be used on its own to great effect. Authentication is more like fudge. There are at least a few ingredients that must brought together in the right way to make it work, and OAuth can be one of these ingredients (perhaps the main ingredient) but it doesn’t have to be involved at all. You need a recipe that says what to combine and how to combine them, and there are a large number of different recipes that say how that can be accomplished.
And in fact, there are a number of well-known recipes out there for doing this with specific providers, like Facebook Connect, Sign In With Twitter, and OpenID Connect (which powers Google’s sign-in system, among others). These recipes each add a number of items, such as a common profile API, to OAuth to create an authentication protocol. Can you build an authentication protocol without OAuth? Of course, there are many kinds out there, just as there are many kinds of non-chocolate fudge to be had out there.
Access of a protected API as proof of authentication Refresh tokens and assertions can be used to get access tokens without the user being present, and in some cases access grants can occur without the user having to authenticate at all. This means that if a client wants to make sure that an authentication is still valid, it’s not sufficient to simply trade the token for the user’s attributes again because the OAuth protected resource, the identity API, often has no way of telling if the user is there or not.
Injection of access tokens An additional (and very dangerous) threat occurs when clients accept access tokens from sources other than the return call from the token endpoint. This can occur for a client that uses the implicit flow (where the token is passed directly as a parameter in the URL hash) and don’t properly use the OAuth state parameter. This issue can also occur if different parts of an application pass the access token between components in order to “share” access among them. This is problematic because it opens up a place for access tokens to potentially be injected into an application by an outside party (and potentially leak outside of the application). If the client application does not validate the access token through some mechanism, it has no way of differentiating between a valid token and an attack token.
This can be mitigated by using the authorization code flow and only accepting tokens directly from the authorization server’s token endpoint, and by using a state value that is unguessable by an attacker.
Lack of audience restriction Another problem with trading the access token for a set of attributes to get the current user is that most OAuth APIs do not provide any mechanism of audience restriction for the returned information. In other words, it is very possible to take a naive client, hand it the (valid) token from another client, and have the naive client treat this as a “log in” event. After all, the token is valid and the call to the API will return valid user information. The problem is of course that the user hasn’t done anything to prove that they’re present, and in this case they haven’t even authorized the naive client.
Injection of invalid user information If an attacker is able to intercept or coopt one of the calls from the client, it could alter the content of the returned user information without the client being able to know anything was amiss. This would allow an attacker to impersonate a user at a naive client by simply swapping out a user identifier in the right call sequence. This can be mitigated by getting the authentication information directly from the identity provider during the authentication protocol process (such as alongside the OAuth token) and by protecting the authentication information with a verifiable signature.
Different protocols for every potential identity provider One of the biggest problems with OAuth-based identity APIs is that even when using a fully standards-compliant OAuth mechanism, different providers will inevitably implement the details of the actual identity API differently. This problem occurs because the mechanisms for conveying authentication information discussed here are explicitly left out of scope for OAuth. OAuth defines no specific token format, defines no common set of scopes for the access token, and does not at all address how a protected resource validates an access token.
A standard for user authentication using OAuth: OpenID Connect OpenID Connect is an open standard published in early 2014 that defines an interoperable way to use OAuth 2.0 to perform user authentication. In essence, it is a widely published recipe for chocolate fudge that has been tried and tested by a wide number and variety of experts. Instead of building a different protocol to each potential identity provider, an application can speak one protocol to as many providers as they want to work with. Since it’s an open standard, OpenID Connect can be implemented by anyone without restriction or intellectual property concerns.
OpenID Connect is built directly on OAuth 2.0 and in most cases is deployed right along with (or on top of) an OAuth infrastructure. OpenID Connect also uses the JSON Object Signing and Encryption (JOSE) suite of specifications for carrying signed and encrypted information around in different places. In fact, an OAuth 2.0 deployment with JOSE capabilities is already a long way to defining a fully compliant OpenID Connect system and the delta between the two is relatively small. But that delta makes a big difference, and OpenID Connect manages to avoid many of the pitfalls discussed above by adding several key components to the OAuth base:
The OpenID Connect ID Token is a signed JSON Web Token (JWT) that is given to the client application alongside the regular OAuth access token. The ID Token contains a set of claims about the authentication session, including an identifier for the user (sub), the identifier for the identity provider who issued the token (iss), and the identifier of the client for which this token was created (aud). Additionally, the ID Token contains information about the token’s valid (and usually short) lifetime as well as any information about the authentication context to be conveyed to the client, such as how long ago the user was presented with a primary authentication mechanism. Since the format of the ID Token is known by the client, it is able to parse the content of the token directly and obtain this information without relying on an external service to do so. Furthermore, it is issued in addition to (and not in lieu of) an access token, allowing the access token to remain opaque to the client as it is defined in regular OAuth. Finally, the token itself is signed by the identity provider’s public key, adding an additional layer of protection to the claims inside of it in addition to the TLS transport protection that was used to get the token in the first place, preventing a class of impersonation attacks. By applying a few simple checks to this ID token, a client can protect itself from a large number of common attacks.
Since the ID Token is signed by the authorization server, it also provides a location to add detached signatures over the authorization code (c_hash) and access token (at_hash). These hashes can be validated by the client while still keeping the authorization code and access token content opaque to the client, preventing a whole class of injection attacks.
User Info Endpoint
It should be noted that clients are not required to use the access token, since the ID Token contains all the necessary information for processing the authentication event. However, in order to provide compatibility with OAuth and match the general tendency for authorizing identity and other API access in parallel, OpenID Connect always issues the ID token alongside an OAuth access token.
In addition to the claims in the ID Token, OpenID Connect defines a standard protected resource that contains claims about the current user. The claims here are not part of the authentication process, as discussed above, but instead provide bundled identity attributes that make the authentication protocol more valuable to application developers. OpenID Connect defines set of standardized OAuth scopes that map to subsets of these attributes: profile, email, phone, and address allowing plain OAuth authorization request to carry the necessary information for a request. OpenID Connect defines a special openid scope that switches on the issuance of the ID token as well as access to the UserInfo Endpoint by the access token. The OpenID Connect scopes can be used alongside other non-OpenID-Connect OAuth scopes without conflict, and the access token issued can potentially be targeted at several different protected resources. This allows an OpenID Connect identity system to smoothly coexist with an OAuth authorization system.
Dynamic server discovery and client registration
OAuth 2.0 was written to allow a variety of different deployments, but by design does not specify how these deployments come to be set up or how the components know about each other. This is OK in the regular OAuth world where one authorization server protects a specific API, and the two are closely coupled. With OpenID Connect, a common protected API is deployed across a wide variety of clients and providers, all of which need to know about each other to operate. It would not be scalable for each client to have to know ahead of time about each provider, and it would be even more unscalable to require each provider to know about each potential client.
To counteract this, OpenID Connect defines a discovery protocol that allows clients to easily fetch information on how to interact with a specific identity provider. On the other side of the transaction, OpenID Connect defines a client registration protocol that allows clients to be introduced to new identity providers. By using these two mechanisms and a common identity API, OpenID Connect can function at internet scale, where no parties have to know about each other ahead of time.
Compatibility with OAuth 2.0
Even with all of this robust authentication capability, OpenID Connect is (by design) still compatible with plain OAuth 2.0, making it a very good choice to deploy on top of an OAuth system with minimal developer effort. In fact, if a service is already using OAuth and the JSON Object Signing and Encryption (JOSE) specifications (including JWT), that service is already well on its way to supporting OpenID Connect already.
To facilitate the building of good client applications, the OpenID Connect working group has published documents on building a basic OpenID Connect client using the authorization code flow as well as building an implicit OpenID Connect client. Both of these documents walk the developer through building a basic OAuth 2.0 client and adding the handful components necessary for OpenID Connect.
OAuth 2.0 Server and Client Libraries may be located for the following platforms and programming languages:
Server libraries for:
Client libraries for:
For additional information in the subject you might be interested in User Authentication with OAuth 2.0 article.
If you have comments or questions regarding this or any post in this blog please leave me a note in the section below this post.
Follow me on Twitter: @john_canessa