Building a project in React for the first time came with many challenges for me. Without a doubt the number one challenge I faced was implementing OAuth.
Since a React app is a completely separate application to any backend (Ruby on Rails API in this case), the state of data has to be carefully orchestrated in the request and response cycle in order to allow for a seamless app experience.
With the GitHub OAuth API there is a very specific flow that you have to follow in order to authenticate a user.
- A user has to be directed to your GitHub auth page.
- A user enters their GitHub username and password.
- Once authenticated GitHub sends the user back to a URL with a temporary code.
- That code now needs to be sent to GitHub with the your OAuth credentials in exchange for a more permanent access token.
- The access token can then be uses to get information about said user.
My Initial Thoughts
At first I thought I could wait for the user to get redirected to a route in the Rails API so I could get the temporary code that is passed back from GitHub and then exchange it for the more permanent access token.
This wouldn't work of course because my application would then lose track of the current user making the login request and I wouldn't be able to log in the user successfully even though I would have all the information about the user from the GitHub API.
So I then naively thought that I could make the API calls from the frontend React app. While this could work. It would be terrible form and open up my app to malitious attack. Storing API credentials in any publicly accessible form is a big no no.
I knew that I could not store any sensitive information on the client side. So I had to use my Rails API to make all the API requests to GitHub. But how?
I took a step back and realized that in order the keep track of the current user making the request to be authenticated. Everything has to be initiated from the client and resolved in the API and sent back to the client in a response.
So here is the flow that worked.
- A user is redirected to the GitHub auth page from the React app.
- The user signs in.
- The user is then redirected back to a page in the React application with a temporary code that can only be used in conjunction with my secret GitHub API key which is kept on the Rails API server.
- At the callback route in the React app, the URL is parsed and the code is sent in a request to the Rails API.
- The Rails API receives the code and makes the request to the GitHub API to get the more permanent access token for this user.
- The Rails API then uses that access token to make another request to the GitHub API to get the users information.
- The Rails API then takes that information and finds or creates a new user.
- The Rails API then sends back a JSON response to the user.
- The user receives the response and is then logged in successfully.
This was really daunting from the outset specifically becuase I had no idea how the response flow with the GitHub API was meant to take place. The hardest part was understanding how this needed to happen. After that the implementation was almost easy.
I was also lucky enough to have some very nice and patient individuals in the Flatiron School Community who helped me to understand the request and response cycle of OAuth authentication.