Wednesday, February 6, 2013

Why OAuth it self is not an authentication framework ?

Let's straight a way start with definitions to avoid any confusions.

Authentication is the act of confirming the truth of an attribute of a datum or entity. If I say, I am Prabath - I need to prove that. I can prove that with something I know, something I have or with something I am. Once I proved my self who I claim I am, then the system can trust me. Sometimes systems do not just want to identify me by just by name. By name could help to identify me uniquely - but how about other attributes of me. Before you get through the border control - you need to identify your self - by name - by picture - and also by finger prints and eye retina. Those are validated real-time against the data from the VISA office which issued the VISA for you. That check will make sure its the same person who claimed to have the VISA enters in to the country. That is proving your identity. Proving your identity is authentication.

Authorization is about what you can do. Your capabilities. You could prove your identity at the border control by name - by picture - and also by finger prints and eye retina - but it's your VISA that decides what you can do. To enter in to the country you need to have a valid VISA that has not expired. A valid VISA is not a part of your identity - but a part of what you can do. Also what you can do inside the country depends on the VISA type. What you do with a B1 or B2 differs from what you can do with an L1 or L2. That is authorization.

OAuth 2.0 is about authorization. Not about authentication.

OAuth 2.0 is about what you can do ( or on behalf of another user) - not about who you are. So - you cannot use OAuth 2.0 it self for authentication.

I hear what you say. We use OAuth 2.0 based Facebook login to log in to plenty of different web applications. So am I lying ?

Let's pick Facebook it self for an example. I got following image from Facebook login developer documentation. It highlights the OAuth flow with authorization code grant type.

User goes to a Web Application. Clicks on the Login button. Gets redirected to the Facebook for authentication and pass the "code" to the client Web Application. Now the Web Application exchanges the code to an access token. Facebook will only issue an access token for a valid code. And - it also will only issue a code after the user been authenticated. So, the Web Application having access to a valid access token means - and it only means - that particular user is from Facebook. That's it. It's like carrying out a valid, stamped VISA to the boarder control with out having any identification information about the user on it. Looking at the access token - the application cannot say who the user is - it can only say where the user comes from. So it does not help the Web Application to identify the end user uniquely. When the same user logs in next time he could bring a different access token - so the Web Application cannot use the access token as a way of identification. That is why OAuth it self is not an authentication framework.

























Still you think I am lying? Of course you do.

When you login via Facebook - your application also gets certain claims about you. Like your first name, last name and email address - and also your Facebook Id. How does this happen if OAuth does not bring any identity attributes ?

Once the Web Application gets the access token from the Facebook, to get user attributes - the Web Application can call following API with the access token it got.

https://graph.facebook.com/me?access_token=[access_token]

This will get the identity information of the user who authorized the access token.

Now - this helps to identify the user - or to authenticate the user. But, keep in mind that the last step is out side the scope of OAuth and that functionality is provided via Facebook's Graph API.

Not just through Facebook's Graph API - even through SCIM we can identify the user. But with the current specification there seems to be a limitation in doing that in a standard manner.

With the current specification to get the details of a specific user we use the following.

 GET /Users/2819c223-7f76-453a-919d-413861904646
 Host: example.com
 Accept: application/json Authorization: Bearer h480djs93hd8

But, just after the OAuth flow - we only have the access token at the client side. No concrete information about the end user. So we cannot use the above.

By having a pre-defined userid say "me" [just like in Facebook Graph API] - cab be made to provide back the logged in user's info.

 GET /Users/me
 Host: example.com
 Accept: application/json
 Authorization: Bearer h480djs93hd8

In the above case - the information about the user corresponding to the provided Bearer token will be returned back. So, based on that, client can identify the end user with it's attributes.

Apart from the above two approaches - OpenID Connect is the best one built on top of OAuth 2.0 to identify the end user.

With OpenID Connect in addition to the OAuth access token - the client or the Web Application also gets an ID token. The ID Token is a security token that contains claims/identity information about the authentication event and other requested claims from the client. The ID Token is represented as a JWT - and it can be used to prove the identity of the end user.

2 comments:

Charitha said...

Excellent post Prabath. Helped me a lot to clear many doubts I had about Authorization and Authentication in OAuth2

Subash Chaturanga said...

Very useful post for a beginner to resolve quite a few glitches. Quite simply explained.