3

I want to let the user sign into my web app using github (after which I can use their name/email, etc.), much like how you can sing into stackoverflow using Google or Facebook. I understand that you have to take the user to the github log in, and once they authenticate your app,you retrieve the code from the url of the page the user is redirected to, and make a POST request using that code to get an access code, which you can use to access the github API. However, when I make the POST request for the access code, I get a CORS error:

Failed to load https://github.com/login/oauth/access_token?client_id=7...&client_secret=b...&code=f...: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.

The response had HTTP status code 404.

This is my POST request:

$.ajax (
{
    url:"https://github.com/login/oauth/access_token?client_id=7...&client_secret=b...&code=" + authCode, // Extraction of authCode has no bugs



    type:'POST',

    dataType:'json',

    success: function() {
    alert('success');
    },
    error: function() {
    alert('error');
    }

});

How do I rectify this so I can integrate the sign in?

EDIT: I cannot use outside applications like gatekeeper. This is a test website, but will ultimately be used in a company's website.

Inori Elric
  • 31
  • 1
  • 3
  • `Access-Control-Allow-Origin` are **response** headers. They must be provided by the server you want permission from. You must not put them in your request headers. They are not allowed there. – Quentin Jul 30 '18 at 10:18

1 Answers1

5

What you're asking is quite complex, and most OAuth applications take even experienced developers days, if not weeks to implement. however, as you've asked I'll try and explain it.

First, you'll have to register your app (https://github.com/settings/applications/new). you'll need to know where your app is. For example, mine's at https://JoelEllis.github.io/github-oauth-app/index.html Then you'll get a client ID - save that somewhere. It'll look like this.

Next, you'll need to decide what scopes your app needs. I'll use read:user but a full list of available scopes are at https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/.

Now you've got most of what you need to create the URL to send the user to. I'll send them using window.location.href. Your URL will look like https://github.com/login/oauth/authorize?client_id=<client-id>&redirect_uri=<redirect_uri>&scope=<scope>. Mine is https://github.com/login/oauth/authorize?client_id=8681b227337ec96cd168&redirect_uri=https://JoelEllis.github.io/github-oauth-app/index.html&scope=read:user.

Next, GitHub will redirect you back to the redirect_uri with a parameter called code, for example, https://JoelEllis.github.io/github-oauth-app/index.html?code=3413cabd1c1a8ba9765f. You need to turn this into an access token next.

To do that you need to send a post request to the URL.

Unfortunately, this can't be done without the client secret, and in most cases, will be blocked by CORB/CORS in the browser. This means that it's a bad, bad idea to get (or use) the access token in the browser. The client secret should never be revealed, as it allows an attacker to pretend to be you.

you'll need a server (can be local) to do everything beyond this point.

You can read the query string in php using $_GET["code"] and in nodejs's express using req.query.code

To make the post request, you'll need your client_id, your client_secret (from the same page you got the client id) and the code you were given by GitHub. You use them to make a URL to post. it'll look like this:https://github.com/login/oauth/access_token/?client_id=<clientid>&client_secret=<clientsecret>&code=<usercode>. This is mine: https://github.com/login/oauth/access_token/?client_id=8681b227337ec96cd168&client_secret=6aaf90fef31d8586da40f3eb90cbc478a1e8b948&code=ba82f2915511cea98ea8.

To post it using PHP, you can use

$url = 'https://github.com/login/oauth/access_token/';
$data = array('key1' => 'value1', 'key2' => 'value2');

'http' => array(
    'header'  => "Content-type: application/x-www-form-urlencoded\r\nUser-Agent: MyApp",
    'method'  => 'POST',
    'content' => http_build_query($data)
)
$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);

And with nodejs:

var request = require('request')
request.post({
  url: 'https://github.com/login/oauth/access_token/?client_id=847b5bc9c960a03d3435&client_secret=92a2e6ac30db45612c4ed6ee4fbca22a95370807&code=' + req.query.code,
  headers: {
    'User-Agent': 'request'
  }
}, function (error, response, body) {
      console.log('hi2');
      console.log(body);
})

When you post it, it will return something that looks like access_token=7d914db556648258e54a37184c9b07d129ab0891&scope=read%3Auser&token_type=bearer. Just add that onto the end of the request to get the response, for example curl https://api.github.com/user/email? + access_token=7d914db556648258e54a37184c9b07d129ab0891&scope=read%3Auser&token_type=bearer.

The full docs can be found at https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/ and https://developer.github.com/v3/. You can see the docs for getting info about users at https://developer.github.com/v3/users/

Community
  • 1
  • 1
Joel Ellis
  • 1,332
  • 1
  • 12
  • 31
  • I've revealed my client secret only for the purpose of this demo, please don't abuse it. :wink: – Joel Ellis Jul 30 '18 at 12:01
  • the example URL is a actual demo i made that returns the URL you need to post to on the server. – Joel Ellis Jul 30 '18 at 12:05
  • Thanks for the great answer! I did everything you mentioned, but I'm getting stuck at the turning the code into the access token. Like you said, I am getting a CORS error and I'm not sure how to bypass that. If it helps, I am using localhost (on XAMPP server). My post request is the original question - I think it looks about right when compared to yours. Thanks! – Inori Elric Jul 30 '18 at 15:29
  • @InoriElric you _can't_ do the code-to-access-token conversion in-browser, and you must specify a user agent- something i got stuck on. ;) on a node.js server this would be ```const request = require('request'); request.post({ url: 'https://github.com/login/oauth/access_token/?client_id=847b5bc9c960a03d3435&client_secret=92a2e6ac30db45612c4ed6ee4fbca22a95370807&code=' + req.query.code, headers: { 'User-Agent': 'request' }``` – Joel Ellis Jul 31 '18 at 12:55