Skip to main content

OAuth 2.0 with GitHub


OAuth 2.0 Demo Application with GitHub API's

What is OAuth 2.0 Authorization Framework?


Today I will be discussing about OAuth 2.0 Framework and how to implement this in a web application along with a demonstration.
The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.

In the traditional client-server authentication model, the client requests a protected resource on the server by authenticating with the server using the resource owner’s credentials. In order to provide third-party applications access to protected resources, the recourse owner shares its credentials with the third party.  This would create several problems and limitations as shown below:
·         Third-party applications are required to store the resource owner’s credentials for future use in clear text.
·         Servers are required to support password authentication, despite the security weaknesses inherent in passwords.
·         Third-party applications gain access to the resource owner’s protected resources, leaving resource owners without any ability to restrict duration or access to a limited subset of resources.
·         Resource owners cannot revoke access to an individual third party without revoking access to all third parties.
·         Compromise of any third-party application results in compromise of the end-user’s password and all of the data protected by that password.

OAuth addresses these issues by introducing an authentication layer and separating the role of the client from the resource owner.
OAuth, the client requests access to resources controlled by the resource owner and hosted by the resource server and is issued a set of different credentials than those of the resource owner. Rather than using the resource owner’s credentials to access the protected information, the client obtains an access token.  An access token is a string with a specific scope and a specific life time and also, with other access attributes.

These access tokens are issued to the third-party clients by authorizing the server with the approval of the resource owner. The client uses the access token to access the protected resources hosted by the resource server.

What are the different roles in OAuth 2.0?


In OAuth 2.0 Framework they have defined some roles as follows:
·         Resource owner
o   It is an entity which can grant the access to a protected resource.
·         Resource server
o   This is the server that is hosting the protected information, capable of accepting and responding to the protected requests using access tokens.
·         Client
o   It is an application that makes protected resource requests on behalf of the resource owner ad with its authorization.
·         Authorization server
o   The server issuing the tokens to the client after successfully authenticating the resource owner and obtaining the authentication.

Authorization Grants and their Types


Authorization Grant is a credential representing the resource owner’s authorization used by the client to obtain an access token.
There are four grant types. They are:
·         Authorization Code
·         Implicit
·         Resource Owner Password Credentials
·         Client Credentials


How to develop the application





In order to create an OAuth flow with GitHub, we need to follow simple 4 steps. Those steps are briefly explain in the above diagram. From this blog we will going to talk about how these 4 steps fulfil and how to create a simple ‘Repository details viewing’ app. 
[Refer GitHub Repo for more details : https://github.com/KMKasunMadusanka/OAuth_Sample_App ]

In order to create this simple Repo viewing application, I have used Angular 6 for front-end development and NodeJs for backend development. Let’s see how to implement this application now.
1.      Register with GitHub dev Portal




First go to the https://github.com/settings/developers and login to the GitHub or create a new account if you do not have an account. Then you will see a screen like bellow. In order to create a new OAuth application click on ‘New OAuth App’ button. And fill the necessary fields accordingly.

Note: - Give valid URL for call back url, because the code which is generated from the GitHub will be send to that URL as a query parameter.

After creating the application, Client id and client secret will be show like bellow.


2.      Generate access code.
 In order to obtain access code, we need to make a GET request to the following URL with the bellow parameters.

GET https://github.com/login/oauth/authorize

      Parameters

NameTypeDescription
client_idstringRequired. The client ID you received from GitHub when you registered.
redirect_uristringThe URL in your application where users will be sent after authorization. See details below about redirect urls.
scopestringA space-delimited list of scopes. If not provided, scope defaults to an empty list for users that have not authorized any scopes for the application. For users who have authorized scopes for the application, the user won't be shown the OAuth authorization page with the list of scopes. Instead, this step of the flow will automatically complete with the set of scopes the user has authorized for the application. For example, if a user has already performed the web flow twice and has authorized one token with user scope and another token with repo scope, a third web flow that does not provide a scope will receive a token with user and repo scope.
statestringAn unguessable random string. It is used to protect against cross-site request forgery attacks.
allow_signupstringWhether or not unauthenticated users will be offered an option to sign up for GitHub during the OAuth flow. The default is true. Use false in the case that a policy prohibits signups.
In our application we have make this GET request in the login page. For that I have used a simple anchor tag with href attribute.  
[Refer Repo: - Angular-Front-end/src/app/components/login/login.component.html]

<div class="main-content">
<div class="title">
Repo Detetails Viewer
</div>
<div class="body">
<a href="https://github.com/login/oauth/authorize?client_id=50f6f7c85489adbadbb9&redirect_uri=http://localhost:4200/mainPage&scope=user&state=123456&allow_signup=false"
class="btn btn-dark btn-md" role="button">
<i class="fa fa-github icon_1"></i>Login with GitHub
</a>
</div>
</div>


Once it load in the browse it looks like bellow.



Once click on the ‘login with GitHub’ button application ask to sign with your GitHub account and ask permission for grant access to the application.




After confirm the authorization, page will automatically redirect to the call back URL (In my case it is: - http://localhost:4200/mainPage ). Within that URL, access token will be shown visible like bellow.




3.      Obtain Access Token
When this page loaded, I have retrieve the code from the query parameter of the URL and send to the backend POST endpoint (http://localhost:5000/accessToken ) with ‘code’ as a parameter.
Then, within that endpoint it calls to the access token generated POST API.
POST https://github.com/login/oauth/access_token

Parameters

NameTypeDescription
client_idstringRequired. The client ID you received from GitHub for your GitHub App.
client_secretstringRequired. The client secret you received from GitHub for your GitHub App.
codestringRequired. The code you received as a response to Step 1.
redirect_uristringThe URL in your application where users are sent after authorization.
statestringThe unguessable random string you provided in Step 1.
Coding implementation is like bellow.
Front End: -
[Reference Path: - Angular-front-end/ src/app/services/ git-hub-service.service.ts]
genrateAccessToken(code:String) {
return this.http.post(this.baseUrl+"/accessToken", {"code":code});
}

Back End:-
[Reference Path: - Node-Back-End/server.js]

app.post('/accessToken', (req, res, next) => {

axios.post('https://github.com/login/oauth/access_token', {
"client_id": "XXXXXXXXXXXX",
"client_secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"code": req.body.code,
"redirect_uri": "http://localhost:4200/mainPage",
"state": "123456"
})
.then(function (response) {
console.log(response.data.split('&')[0].split('=')[1]);
res.send({ "access_token": response.data.split('&')[0].split('=')[1] })
})
.catch(function (error) {
console.log(error);
});
})

4.      Access the GitHub API’s with Access token.
Once access token is generated. We can call to the GET request and get the particular user details as bellow.
GET https://api.github.com/user?access_token=...

Output:-


{
"login":"KMKasunMadusanka",
"id":25845466,
"node_id":"MDQ6VXNlcjI1ODQ1NDY2",
"avatar_url":"https://avatars3.githubusercontent.com/u/25845466?v=4",
"gravatar_id":"",
"url":"https://api.github.com/users/KMKasunMadusanka",
"html_url":"https://github.com/KMKasunMadusanka",
"followers_url":"https://api.github.com/users/KMKasunMadusanka/followers",
"following_url":"https://api.github.com/users/KMKasunMadusanka/following{/other_user}",
"gists_url":"https://api.github.com/users/KMKasunMadusanka/gists{/gist_id}",
"starred_url":"https://api.github.com/users/KMKasunMadusanka/starred{/owner}{/repo}",
"subscriptions_url":"https://api.github.com/users/KMKasunMadusanka/subscriptions",
"organizations_url":"https://api.github.com/users/KMKasunMadusanka/orgs",
"repos_url":"https://api.github.com/users/KMKasunMadusanka/repos",
"events_url":"https://api.github.com/users/KMKasunMadusanka/events{/privacy}",
"received_events_url":"https://api.github.com/users/KMKasunMadusanka/received_events",
"type":"User",
"site_admin":false,
"name":"Kasun Madusanka",
"company":null,
"blog":"",
"location":null,
"email":null,
"hireable":null,
"bio":null,
"public_repos":20,
"public_gists":0,
"followers":3,
"following":8,
"created_at":"2017-02-17T13:25:43Z",
"updated_at":"2018-10-14T06:49:30Z",
"private_gists":0,
"total_private_repos":0,
"owned_private_repos":0,
"disk_usage":100065,
"collaborators":0,
"two_factor_authentication":false,
"plan":{
"name":"free",
"space":976562499,
"collaborators":0,
"private_repos":0
}
}

Using these data we can show the Repo details details as bellow.


Comments