A Technology Blog About Code Development, Architecture, Operating System, Hardware, Tips and Tutorials for Developers.

Tuesday, February 12, 2013

OAuth2 - In a Simple Way

11:40:00 PM Posted by Satish , , , , , 5 comments
Last week I started playing with OAuth 2.0. I started with a github project called spring-security-oauth. I checked the sample OAuth 2 provider sparklr and OAuth 2 client tonr. But I could not get much from the sample example and the documentation provided. I explored a bit in the internet and finally could able to conclude some thing. I created a sample provider and checked all authorization on that. Now, I am here to explain different aspects of OAuth 2.0 from the practical point of view. I will try my best to present a modular and easy explanation here.


Many services such as Facebook, Github, and Google have already implemetated OAuth 2.0. That is why today most of the web sites using google/ facebook for authentication and authorization. They work as resource server, from where other clients fetch profile informations.

This post is an attempt to describe OAuth 2.0 in a simplified format to help developers and service providers implement the protocol.

I will be covering the following topics in this article.

1. Entities
2. Creating an Application
3. Authorization
a. Web Server Apps
b. Browser-Based Apps
c. Mobile Apps
d. Others
4. Accessing Resources
5. Resources


OAuth 2 Entities
OAuth 2 Entites


Entities:

OAuth Server:
This is also known as OAuth Provider. It's whole responsibility is to authenticate and authorize user/ client and manage the tokens. 

The Third-Party Application:
Third-Party Application popularly known as client, is going to attempt to get access to the user's account. It needs to get permission from the user, before it can do so. This could be a web server based application, browser based application, desktop application, mobile/tablet application or some smart devices like google Goggles and smart televisions. 

Resource Server:
The API popularly known as Resource Server, from where the data will be fetched out or served. This could be the SOAP or REST based service providers.

The User:
The User popularly known as Resource Owner, who gives access to access the resource.

Creating an Application:

Before you can begin the OAuth process, you must first register a new app with the service/provider. When registering a new app, you usually register basic information such as application clint id, secret, authorized-grant-types etc. In addition, you must register a redirect URI to be used for redirecting users to for web server, browser-based, or mobile apps.

Redirect URIs:
The service will only redirect users to a registered URI, which helps prevent some attacks. Any HTTP redirect URIs must be protected with SSL security, so the service will only redirect to URIs beginning with "https". This prevents tokens from being intercepted during the authorization process.

Client ID and Secret:
After registering your app, you will be having your client ID and a client secret. The client ID is considered public information, and is used to build login URLs, or included in Javascript source code on a page. The client secret must be kept confidential. If a deployed app cannot keep the secret confidential, such as Javascript or native apps, then the secret is not used.

Authorization:

The first step of OAuth 2 is to get authorization from the user. For browser-based or mobile apps, this is usually accomplished by displaying an interface provided by the service to the user.

OAuth 2 provides several grant types for different use cases. The grant types defined are:

Authorization Code for apps running on a web server
Implicit for browser-based or mobile apps
Password for logging in with a username and password
Client credentials for application access

Web Server Apps
Web apps are written in a server-side language and run on a server where the source code of the application is not available to the public.

Authorization request:

http://localhost:8080/oauth2/oauth/authorize?response_type=code&client_id=easylocate&scope=read&redirect_uri=http://localhost:8080/web

After accepting the access. the page will be redirected to the redirect uri with the authorization code.

http://localhost:8080/web/?code=t7ol7D

Now it is time to exchange the authorization code to get the access token.

http://localhost:8080/oauth2/oauth/token?grant_type=authorization_code&code=t7ol7D&redirect_uri=http://localhost:8080/web&client_id=easylocate&client_secret=secret

The OAuth server replies with the access token

1
2
3
4
5
6
7
{
  "access_token": "372c3458-4067-4b0b-8b77-7930f660d990",
  "token_type": "bearer",
  "refresh_token": "ce23c924-3f28-456c-a112-b5d02162f10c",
  "expires_in": 37364,
  "scope": "read"
}

In case of wrong authorization code, Oauth server replies error.

1
2
3
4
{
  "error": "invalid_grant",
  "error_description": "Invalid authorization code: t7olD"
}

Security: Note that the service should require apps to pre-register their redirect URIs. Or else there will be a mismatch.

Browser-Based Apps & Mobile Apps:
Browser-based apps run entirely in the browser after loading the source code from a web page. Since the entire source code is available to the browser, they cannot maintain the confidentiality of their client secret, so the secret is not used in this case.

Authorization request:

http://localhost:8080/oauth2/oauth/authorize?response_type=token&client_id=easylocate&redirect_uri=http://localhost:8080/web&scope=read

After accepting the access. the page will be redirected to the redirect uri with the token.

http://localhost:8080/web/#access_token=372c3458-4067-4b0b-8b77-7930f660d990&token_type=bearer&expires_in=37026

That's it, there's no other steps! At this point, some Javascript code can pull out the access token from the fragment (the part after the #) and begin making API requests.

If there is an error, you will instead receive an error in the URI fragment, such as:

http://localhost:8080/web/#error=invalid_scope&error_description=Invalid+scope%3A+rea&scope=read+write

Password Based:
OAuth 2 also provides a password grant type which can be used to exchange a username and password for an access token directly. Since this obviously requires the application to collect the user's password, it should only be used by apps created by the service itself. For example, the native Twitter app could use this grant type to log in on mobile or desktop apps.

To use the password grant type, simply make a POST request like the following. I am using the curl tool to demonstrate the POST request. You may use any rest client.

curl -i -X POST -d "client_id=easylocate&grant_type=password&username=admin&password=admin&client_secret=secret" http://localhost:8080/oauth2/oauth/token

The server will get back with the token

1
2
3
4
5
6
7
{
  "access_token": "4e56e9ec-2f8e-46b4-88b1-5d06847909ad",
  "token_type": "bearer",
  "refresh_token": "7e14c979-7039-49d0-9c5d-854efe7f5b38",
  "expires_in": 36133,
  "scope": "read write"
}

Client Credential Based:
Client credentals based authorization is used for server to server application access. I am just showing a POST request using the curl tool.

curl -i -X POST -d "client_id=easylocate&grant_type=client_credentials&client_secret=secret" http://localhost:8080/oauth2/oauth/token

Server will get back with the access token

1
2
3
4
5
6
{
  "access_token": "9cd23bef-ae56-46b0-82f5-b9a8f78da569",
  "token_type": "bearer",
  "expires_in": 43199,
  "scope": "read write"
}

Accessing Resources:

Once you are been authenticated and got the access token, you can provide the the access token to access the protected resources.

1
curl -i -H "Authorization: Bearer 4e56e9ec-2f8e-46b4-88b1-5d06847909ad" http://localhost:8080/oauth2/users

I have created my OAuth2 server/provider using spring oauth2 api. I will be creating deferent types of clients and services to demonstrate more. I am not that good in mobile app development, appreciate if some one fork the project and add sample mobile applications. I have shared the code at GitHub.

Resources: