## OAuth Flow If you have a service which needs to interact with the GitHub API on behalf of a user, you should use the OAuth flow. [Phil Haack](https://haacked.com) has written a great [blog post](http://haacked.com/archive/2014/04/24/octokit-oauth/) on using Octokit in ASP.NET, and even has a [demo project](https://github.com/Haacked/octokit-oauth-demo) you can try out, so this will just go over the specific APIs in more detail. ### Setup First, you need to register your application on GitHub (or GitHub Enterprise). While logged in, go to your account settings and click the Applications tab. Then click "Register new application". Or just navigate to [https://github.com/settings/applications/new](https://github.com/settings/applications/new) if you're lazy. Fill in some details about your application: ![application registration](https://cloud.githubusercontent.com/assets/19977/2760125/62600c38-c9ae-11e3-911f-783d7a34aeaf.png) Then click "Register application", and you'll get your client id and client secret. ![OAuth application registration details](https://cloud.githubusercontent.com/assets/19977/2760128/95587e40-c9ae-11e3-84f2-053d2574f1e8.png) ### Starting the OAuth Flow We'll use these in a few places, so define these as private fields: ```csharp var clientId = "some-id-here"; var clientSecret = "some-id-here"; var client = new GitHubClient(new ProductHeaderValue("my-cool-app")); ``` To start the authentication flow, you need to craft a URL indicating your application needs to authenticate on behalf of the current user. ```csharp // NOTE: this is not required, but highly recommended! // ask the ASP.NET Membership provider to generate a random value // and store it in the current user's session string csrf = Membership.GeneratePassword(24, 1); Session["CSRF:State"] = csrf; var request = new OauthLoginRequest(clientId) { Scopes = {"user", "notifications"}, State = csrf }; // NOTE: user must be navigated to this URL var oauthLoginUrl = client.Oauth.GetGitHubLoginUrl(request); ``` Scopes are keys which specify the permissions the application needs. If you don't specify a `Scopes` value, your application will only have read access to the user's public data (repository, user info, etc). There's lots of different scopes available for different interactions with user data, so have a look at the [documentation](https://developer.github.com/v3/oauth/#scopes) for more information. ### Generating the token Once the user has been navigated to the URL above and clicked "Authorize Application", you will receive a callback at the default Callback URL for your application. If you require a more flexible URL, you can override this by specifying a different URL when creating the request. ```csharp var request = new OauthLoginRequest(clientId) { // other parameters RedirectUri = new Url("https://mycoolsite.com/some/uri") }; ``` The callback will have two parameters, the code generated by the GitHub API and some additional state - this is specifically to prevent CSRF (Cross-Site Request Forgery) attacks and is highly recommended. With this code you can then request an access token by providing your client secret. This doesn't require any user interaction, so it can be done in the background. ```csharp public async Task Authorize(string code, string state) { if (String.IsNullOrEmpty(code)) return RedirectToAction("Index"); var expectedState = Session["CSRF:State"] as string; if (state != expectedState) throw new InvalidOperationException("SECURITY FAIL!"); Session["CSRF:State"] = null; var request = new OauthTokenRequest(clientId, clientSecret, code); var token = await client.Oauth.CreateAccessToken(request); Session["OAuthToken"] = token.AccessToken; return RedirectToAction("Index"); } ``` And now you have an access token, you can set up your credentials to use this token: ```csharp // repositories which include public and private repositories. public async Task Index() { var accessToken = Session["OAuthToken"] as string; if (accessToken != null) { client.Credentials = new Credentials(accessToken); var repositories = await client.Repository.GetAllForCurrent(); } /* TODO: all the rest of the webapp */ } ```