OAuth is not authentication. It’s an authorization protocol, or, better yet, a delegation protocol. It’s for this reason that authentication protocols such as OpenID Connect exist and legacy protocols such as SAML use extension grants to link authentication and delegation.
There are articles on this subject already, but I still regularly see some confusion as to the reasons why on the internet and with new clients. So in this article, I’m going to discuss the key reasons why OAuth on its own does not provide client applications (relying parties) with user authentication.
TL;DR: OAuth != authentication. For authentication use OpenID Connect, don’t hack it yourself.
Authentication vs. Authorization
Before we start, let’s clarify the difference between authentication and authorization:
- Authentication is the process of verifying an identity (who they say they are)
- Authorization is the process of verifying what someone is allowed to do (permissions)
This is how I differentiate these terms in my head. Your mileage may vary.
Access Tokens are Not Intended for the Client
Let’s start with the biggest reason why OAuth isn’t authentication: access tokens are not intended for the client application.
When an authorization server issues an access token, the intended audience is the protected resource. After all, this is what the token is providing access to. It’s down to the protected resource to understand and validate the token. One of the benefits of OAuth is that the protected resource doesn’t even need to know who the requesting client application is, just what permissions it has been delegated.
In OAuth, all the client application needs to do is to request the token, use it to access the resource, and then handle the response (both success and failure).
Access Tokens do Not Represent a User
Instead, an access token represents the delegated permissions that the resource owner (the user) has given the client application. An access token could contain information about the user who delegated permission, but it does not actually represent the user.
Access Tokens do not Represent Authentication
An access token also does not represent or give any indication of a user having authenticated. There may not even be a user present! It could have been a machine using client credentials, or even impersonation using ROPC.
Access Tokens can be Anything and Contain Anything
There is no standard structure for an access token. So even though the past two points sound like they could be worked around, there’s no guarantee that your client application would be able to understand it.
If you are relying on an access token being a structured piece of data, there’s also no reason it can’t change its structure at any time. Only the authorization server and relying parties get a say in the access token structure; client applications don’t get a say.
As I was writing this, Vittorio Bertocci wrote a similar article after finding some Microsoft Graph API users using Azure access tokens for user authentication, again dispelling some myths around their usage.
Access Tokens cannot be Safely Verified by the Client Application
Yes, even if you are using a JWT, there is not much hope for a client application to receive access tokens and be sure that no one cut and paste that token from a different request. This is because you are not the intended audience of the token, and also have no way of matching the received token to your request.
This issue is covered in detail by John Bradley in his article “The problem with OAuth for Authentication”, this time focussing on Facebook Connect.
What about Resource Owner Password Credentials (ROPC)?
Don’t get me started on ROPC. Just because this grant type contains user credentials, doesn’t mean the that the resulting token represents a user, or the act of a user authenticating. Instead, it is the impersonation of the user by the client application. Take a look at my rant on ROPC for more details.
“Ah, but that could be worked around by…”
If your answer to any of the above points starts with the above statement: Stop and take a look into OpenID Connect. OpenID Connect is an authentication protocol built on top of OAuth, is already widely adopted, and really does offer solutions to each of the points above. Please don’t make another MyOwnOAuth™.