learn-co-students / rails-github-api-v-000

Other
2 stars 790 forks source link

Working with APIs

In this lab, we're going to dive into GitHub's OAuth functionality and build our own OAuth Rails application. Refer to this tutorial and the Github OAuth documentation as you work through this lab.

Objectives

Instructions

  1. First, Set up a new OAuth application on GitHub. For the 'Authorization callback URL' we can use http://localhost:3000/auth. Once set up, you will be provided a Client ID and Client Secret.

  2. Create a .env file where you can store your unique ID and Secret as GITHUB_CLIENT and GITHUB_SECRET. The dotenv gem will read this file, finds out our secrets and securely passes them to our Rails app.

  3. Our Rails application will need to mimic GitHub's OAuth web application flow. The following routes are provided:

get '/auth' => 'sessions#create'
post '/repositories/create' => 'repositories#create'
root 'repositories#index'

A user visiting http://localhost:3000/ will be routed to the root path. Before repositories#index can be invoked, we want to check if the user is authenticated. Write authenticate_user and logged_in? methods in application_controller.rb that will be called before every action. In authenticate_user, if the user isn't logged in (i.g. no session token), we will redirect to GitHub. The base URL here will be https://github.com/login/oauth/authorize and will use the Client ID as a parameter.

  1. If set up properly, running rails s and heading to http://localhost:3000 should cause a GitHub login to appear. Don't worry about authorizing just yet (it is possible to get stuck in a loop here, redirecting to GitHub over and over, since we haven't finished our application). Since we set the 'Authorization callback URL' to http://localhost:3000/auth, once a user signs in to GitHub and authorizes the use of OAuth, they will be redirected back to our app and routed to sessions#create.

  2. In sessions_controller.rb, write a create method. This method should receive GitHub's code parameter and should use it in conjunction with your Client ID and Client Secret to send a POST request to GitHub. The base URL this time will be https://github.com/login/oauth/access_token.

    Note: It is entirely possible to get this workflow working using query params appended to the end of the URL (i.g. https://github.com/login/oauth/access_token?client_id=...). However, it is generally best for security to not send IDs, secrets and tokens this way. Instead, we typically send this content in request headers or in the body.

    For GitHub, we will include our Client ID, Secret and code as part of the body of the request:

    response = Faraday.post "https://github.com/login/oauth/access_token" do |req|
      req.body = { 'client_id': client_id, 'client_secret': client_secret, 'code': code }
      req.headers['Accept'] = 'application/json'
    end

    Notice here, we are also including an 'Accept' header, as well. In this case, we are telling GitHub's server that we will accept JSON as a response.

    If the credentials are correct, GitHub will send a response that includes headers and a body. Within the body is an access token unique to this specific request.

    As is the case whenever data is sent from an API or web server, the response body is sent in the form of a string. Before we can get data from this string, we will need to parse it into a hash:

    body = JSON.parse(response.body)

    The above code parses the response body into a Ruby hash and stores this hash as the body variable. Whatever key value pairs were sent by GitHub will now be available, including body['access_token'].

    We will need this token whenever we send API requests, so the best place to store this would be with in session. Setting something like session[:token] to be equal to the parsed 'access_token' value will allow us to access the token in other controllers.

    After parsing and storing the token as a value in session, redirect to our root path at the end of the create method.

  3. When we are routed to repositories#index, our root path, authenticate_user is called again. This time, however, since there is now a session[:token], the user will not redirected and our repositories/index.html.erb file will be displayed.

  4. Call the GitHub API from within repositories#index to retrieve and display the current user's 'login' in repositories/index.html.erb.

  5. Call the API a second time using https://api.github.com/user/repos to retrieve and display a list of repositories on repositories/index.html.erb. Displaying only the first page of results is fine; feel free to tackle pagination as a bonus.

BONUS: Implement a create action in your RepositoriesController so that the form on index.html.erb successfully creates a new repository for the current user. The form input should be the name of the new repository. Redirect back to '/'. If successful, you should be able to see your newly created repository on your GitHub account.

Hint: You may not be able to trigger pry when testing your application with rails s. However, if you include binding.pry in your controllers, you can trigger it when running tests.

View Working with APIs on Learn.co and start learning to code for free.