public

GitHub OAuth Busy Developer's Guide

  • Download Gist
github_oauth_busy_developer_guide.md
Markdown

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

If you have questions about the document itself (typos, more references, suggestions, etc), post them here. If you want to discuss GitHub OAuth in general, see the API forum.

Do the access tokens expire? I don't see a refresh token returned.

How should I "check back in" with Github to ensure that the access token is still valid? Will the API calls fail in a clearly defined way when the access token is invalid?

Tokens don't have to expire. From what I read about Facebook's implementation, they only send back the access token and an expiration if the offline_access scope is not requested. Right now, GitHub just assumes all apps want offline access.

Are port numbers significant? I registered localhost:9393 and localhost:9292 works too.

@technoweenie: ok, thanks.

Ah, I don't think I do much validation of the callback_uri. I should definitely do that. I wasn't exactly sure how the specs wanted to handle that though.

What's wrong with using a port number? I'm using that in one of my tests. I put 127.0.0.1 myapp.local in my /etc/hosts and registered an app here for http://myapp.local:8080/auth/github-callback.

I'm using a port number as well, the problem is that there's no port validation happening on the github side. I'm not familiar enough with oauth to know whether or not it should validate that the port number is correct which is why I asked.

Try running your app on 8181 and you'll see that your keys work there too.

I'll probably add uri validation. So if you have http://myapp.com:81/foo...

However, I don't think the specs are super clear on what to do in that case.

I just added redirect uri validation, as well as support for the desktop flow.

Where does the client secret come into play with the desktop workflow?

You're right, this looks like a flaw in the specs. I'll read over them again and see if I missed something. I really don't like how they skip the temporary code process. There's no reason why JS or desktop apps couldn't make a second request to get the access token like the web server flow.

Can we get deploy key access enabled for the oauth side of thigns too? It works with the login/token combo but not with the access_token.

It'll probably be after RailsConf. I'm still in the process of auditing those API actions and sprinkling in OAuth support.

The user_agent flow (used for js/desktop logins) is disabled for now. I need to figure out how to implement it properly according to spec.

Clarified the user/repo/public_repo scopes. The repo and public_repo scopes are implemented for issue api calls, and repo deploy keys.

First of all, this is awesome! My use case is actually one which doesn't involve separating the user from the application, but just interacting with my own account via the API. Ideally I could use the OAuth client credentials flow to trade my API token for an access token?

The normal access token should work just fine for your needs. Perhaps they're going to remove the token based auth in the future but it's probably better to familiarize yourself w/ the API and learn the OAuth side when you're building things for more than just yourself.

I'd like to keep access token support around for personal use. There are some things we likely won't ever allow through OAuth, such as managing public keys and passwords. So right now, we don't plan to ever deprecate access tokens :)

If I'm understanding you correctly, this means that I can take my existing API token and use it as an OAuth 2.0 access token? If so, exactly what I was looking for.

No, the API accepts your token without OAuth. See the Authentication section in http://develop.github.com/p/general.html

Think of OAuth as a way for an app to generate a new token for you that only works on that app.

Any update on the deploy key access to repository?
I tried to add deploy keys using oauth and get a 401

I'm pretty sure you need to invalidate your current token and fetch a new one w/ the repo scope defined.

I'm still seeing issues with fetching a user's public keys and adding deploy keys.

Fixed a caching bug related to the tokens :) It wasn't storing the scopes right in memcache. As soon as CI comes back green, I'll deploy and clear existing oauth caches.

Should /repos/pushable be returning unauthorized if you specified the repos scope?

What's the status of this?

https://github.com/login/oauth/authorize just gives me a 404

It works fine, but still has a lot of rough edges. You need to pass a client_id and redirect_uri to that URL.

strange, I did that using the Oauth2 gem but it doesn't work, it seems to generate the wrong URL.

Manually entering the URL works, so must be something on my end.

Thanks!!

OK I needed to add some extra params otherwise OAuth2 generates some standard URLs. This works for me

  opts = {
    :authorize_url    => 'https://github.com/login/oauth/authorize',
    :access_token_url => 'https://github.com/login/oauth/access_token',
    :site             => 'https://github.com'    
  }    
  @client ||= OAuth2::Client.new(GITHUB_CLIENT_ID, GITHUB_SECRET, opts)

As a user, will I be able to give read-only access to my stuff?

Thats one of the things that I don't like with Twitter for example: a lot of apps would only need RO, but Twitter gives out RW tokens.

Does the API support creating post-receive hooks from there? I can't find documentation, but maybeeeee… :)

@foca - i'm planning on adding that soon if i make the time for it.

I'm trying to upload a ssh key http://develop.github.com/p/users.html with and OAuth access token. I'm attaching the "access_token" as parameter to the URL and send the key in the POST body. It looks right to me but I always get a 401 message back.

Is this API supposed to work with OAuth?

@fjakobs We don't support uploading user's ssh keys with OAuth right now. At this point we're unsure if we'll ever add that feature to the API. Uploading deploy keys does work however.

@atmos thanks for the information. Though I think uploading deploy keys has the same security implications as uploading public keys. Both give you read/write access to any repository. Either both should be allowed or both disallowed. What about adding an SSH OAuth scope?

@kjakobs: Ah you're totally right about deploy keys! I thought they were readonly for some reason. I'll be removing them today.

I'm not sure we'll ever add support for key management in OAuth:

  • You rarely have to update keys.
  • Keys will be a thing of the past when Smart HTTP support in Git improves.

Noooooooooo!!!! :)

We're actually using OAuth to add deploy keys (and hopefully post-receive hooks, if Corey finds the time for that). Could you leave them there? :)

Once they are a thing of the past and there's an alternative, I'd be glad to transition to something different, but I would rather minimize the steps users have to go through, if possible :)

Cheers

Blah, I just realized the API lets you modify org teams and repo collaborators, so any discussion on public key is probably moot.

What about reading public keys? It would be incredibly useful for us to be able to check if the user has already uploaded the key manually.

How can I revoke the applications access? I know this is beta, but still, you need to provide us with a way to let the users revoke access.
Edit: Just realized you can do this under 'connections' - this could be clearer.

I just added the gist scope for creating gists, and support for accessing git objects on private repos.

so is there an API for writing to gists now?

Create a gist is Coming soon on http://develop.github.com/p/gist.html

Oh, I guess whoever added it never updated the docs. Just post to https://github.com/api/v1/json/new with the same fields as the web form. It's kind of weird, so maybe that's why it's not public yet :)

I would like to pull and push repositories using the access token that I get from OAuth so that the user doesn't have to trust our service with key-pairs. Will that ever be possible? At present I guess I need to create and deploy a key-pair on the users behalf and then store the private key in a safe place. The deploy method is
marked deprecated though, and that makes me a bit worried.

What does the future look like for services that want to push on behalf of a user?

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

what is the expires_in of the GitHub token

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.

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

+1 read-only specific private repo

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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.