Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
GitHub OAuth Busy Developer's Guide

GitHub OAuth Busy Developer's Guide

This is a quick guide to OAuth2 support in GitHub for developers. This is still experimental and could change at any moment. This Gist will serve as a living document until it becomes finalized at Develop.GitHub.com.

OAuth2 is a protocol that lets external apps request authorization to private details in your GitHub account without getting your password. All developers need to register their application before getting started.

Web Application Flow

  • Redirect to this link to request GitHub access:
https://github.com/login/oauth/authorize?
  client_id=...&
  redirect_uri=http://www.example.com/oauth_redirect
  • If the user accepts your request, GitHub redirects back to your site with a temporary code in a code parameter. Exchange this for an access token:
POST https://github.com/login/oauth/access_token?
  client_id=...&
  redirect_uri=http://www.example.com/oauth_redirect&
  client_secret=...&
  code=...

RESPONSE:
access_token=...
  • You have the access token, so now you can make requests on the user's behalf:
GET https://github.com/api/v2/json/user/show?
  access_token=...

Javascript Flow

Disabled, for now...

Desktop flow

Disabled, for now...

Scopes

  • (no scope) - public read-only access (includes user profile info, public repo info, and gists).
  • user - DB read/write access to profile info only.
  • public_repo - DB read/write access, and Git read access to public repos.
  • repo - DB read/write access, and Git read access to public and private repos.
  • gist - write access to gists.

Your application can request the scopes in the initial redirection:

https://github.com/login/oauth/authorize?
  client_id=...&
  scope=user,public_repo&
  redirect_uri=http://www.example.com/oauth_redirect

References

@technoweenie
Copy link
Author

technoweenie commented Feb 1, 2011

File a support issue if you have any more questions about OAuth and the API.

@bassemZohdy
Copy link

bassemZohdy commented May 4, 2013

what is the expires_in of the GitHub token

@antn
Copy link

antn commented Jul 8, 2013

The "register their application" link should point to https://github.com/settings/applications/new, not https://github.com/account/applications/new.

@w1150n
Copy link

w1150n commented Jul 25, 2013

When will we be able to only grant access to specific private repos? Exposing access to all private repos is a deal-killer for us.

@juansalas
Copy link

juansalas commented Jul 26, 2013

Yes, agree with w1150n. Is there any way to select private repos or at least provide a read-only permission for private repos ?? Thanks!

@jperl
Copy link

jperl commented Jul 27, 2013

+1 read-only specific private repo

@Zeokat
Copy link

Zeokat commented Mar 5, 2014

Zeokat says, thanks for the code. Deal with Oauth is oauughrrg.

@jasonhargrove
Copy link

jasonhargrove commented Jul 2, 2014

+1 specified repos

@Malabarba
Copy link

Malabarba commented Jul 22, 2015

Has the workflow changed recently? Trying to post on https://github.com/login/oauth/access_token only gives me a Not Found error.

@dkhmelenko
Copy link

dkhmelenko commented Aug 5, 2015

Same for me. Receive Not Found when trying to post on https://github.com/login/oauth/access_token. Does anybody know the reason?

@fallanic
Copy link

fallanic commented Jan 20, 2016

+1 read-only private repo

@masud-technope
Copy link

masud-technope commented Apr 3, 2016

Is the Javascript flow available now? It was much needed for me.

@luizkowalski
Copy link

luizkowalski commented Aug 1, 2016

+1 for javascript flow

@chadwithuhc
Copy link

chadwithuhc commented Nov 12, 2016

For those getting 404 errors:

I had the same problem and ended up here. This was a solution to my problem:

function requestGithubToken(options, code) {
  let data = new FormData()
  data.append('client_id', options.client_id)
  data.append('client_secret', options.client_secret)
  data.append('code', code)
  
  fetch(`https://github.com/login/oauth/access_token`, {
    method: 'POST',
    body: data
  })
  .then((response) => {
    return response.text()
  })
  .then((paramsString) => {
    let params = new URLSearchParams(paramsString)
    console.log('access_token', params.get('access_token'))
  });
}

Part of the problem was my data was sent as JSON and not FormData. Then dealing with the response I had to use URLSearchParams to pull out the access token.

@nathandunn
Copy link

nathandunn commented Nov 22, 2016

+1 for sending as FormData instead of JSON. That should be more prevalent in the doc since everything else I seem to send it encoded JSON.

@lakesare
Copy link

lakesare commented Jan 29, 2017

@chadwithuhc, ugh, thank you, spent a few hours on this (was sending JSON.stringify data too). this should most certainly be somewhere in docs.
FormData worked.

@McaDipali
Copy link

McaDipali commented Mar 24, 2017

hey nice post but i want to ask something....
imagine that there are admin & client two user of application
admin set up client id and secrete for application then who will set the scope of the token
i mean admin or client ?

@srph
Copy link

srph commented Jul 14, 2017

The FormData workaround for POST to https://github.com/login/oauth/access_token doesn't seem to be working anymore - still getting a 404 pre-flight response. Any ideas why?

@roydekleijn
Copy link

roydekleijn commented Aug 5, 2017

jeah... having the same on the preflight... like to know the solution

@brianmcallister
Copy link

brianmcallister commented Sep 24, 2017

Remember to set the header Content-Type: application/json if you want to send JSON data.

@tscanlin
Copy link

tscanlin commented Oct 3, 2017

^ Thank you!

Add accept headers to get JSON back too

headers: {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
},

@henrysoftware6
Copy link

henrysoftware6 commented May 8, 2018

I'm trying to do a rest api get request with

@henrysoftware6
Copy link

henrysoftware6 commented May 8, 2018

I'm trying to do a rest api get request with
https://github.com/login/oauth/authorize?client_id=**********&redirect_uri=http://localhost:****. but I don't see any Code in my Get response, where can I find my "Code" in the GET response?

@msudgh
Copy link

msudgh commented Jul 8, 2018

Is it right to use client_secret in a open source project which is visible for everyone? or have security concerns for OAuth apps? @technoweenie

@gajus
Copy link

gajus commented Mar 19, 2019

Is it right to use client_secret in a open source project which is visible for everyone? or have security concerns for OAuth apps? @technoweenie

Definitely not Okay.

Secret token in combination with client ID is enough to access all user information.

@jayporta
Copy link

jayporta commented May 31, 2019

Is it right to use client_secret in a open source project which is visible for everyone? or have security concerns for OAuth apps? @technoweenie

Definitely not Okay.

Secret token in combination with client ID is enough to access all user information.

But if we're putting the client secret and ID in the URL, anyone can easily find them in the browser's network tab.

@Kameshwaran
Copy link

Kameshwaran commented Aug 7, 2019

function requestGithubToken(options, code) {
  let data = new FormData()
  data.append('client_id', options.client_id)
  data.append('client_secret', options.client_secret)
  data.append('code', code)
  
  fetch(`https://github.com/login/oauth/access_token`, {
    method: 'POST',
    body: data
  })
  .then((response) => {
    return response.text()
  })
  .then((paramsString) => {
    let params = new URLSearchParams(paramsString)
    console.log('access_token', params.get('access_token'))
  });
}

This works!

@bhaumik55231
Copy link

bhaumik55231 commented Dec 1, 2021

function requestGithubToken(options, code) {
  let data = new FormData()
  data.append('client_id', options.client_id)
  data.append('client_secret', options.client_secret)
  data.append('code', code)
  
  fetch(`https://github.com/login/oauth/access_token`, {
    method: 'POST',
    body: data
  })
  .then((response) => {
    return response.text()
  })
  .then((paramsString) => {
    let params = new URLSearchParams(paramsString)
    console.log('access_token', params.get('access_token'))
  });
}

I'm getting a CORS error when trying to run it locally. Anyone else having the same issue?

Access to fetch at 'https://github.com/login/oauth/access_token' from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

@hiroshinishio
Copy link

hiroshinishio commented May 29, 2022

This worked for me.
The problem is not whether JSON or FormData, just to be embarrassed, misspelled.
Hope this helps.

clientId -> client_id
clientSecret -> client_secret

const GetGithubAccessToken = async (
  req: NextApiRequest,
  res: NextApiResponse
) => {
  const body = {
    client_id: process.env.NEXT_PUBLIC_GITHUB_CLIENT_ID,
    client_secret: process.env.NEXT_PUBLIC_GITHUB_CLIENT_SECRET,
    code: req.body.code
  };
  const url = 'https://github.com/login/oauth/access_token';
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(body)
  })
    .then((res) => res.json())
    .catch((err) => {
      console.log({ err });
      return err;
    });
  res.status(200).json(response);
};

@khalid-jarrad
Copy link

khalid-jarrad commented Jul 14, 2022

+1 a CORS error when trying to run it locally, any solution please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment