Google Oauth2 on Rails w/ OmniAuth
Published: 2020-08-23 04:58:53

This week, I tried to focus mainly on my project and started working on the authentication portion of the project. In order to do this, there was an array of different options I could have gone with including the one that I became familiar with at FlatIron. However, I thought that would be a bit boring, and so I decided to go with Google authentication. Nowadays whicever website you go on, you'll find the easy to use on click solution to signing in, where users don't have to go through a tedious sign up page, since Google provides all the authentication information and processes. I want to share the method I chose to implement authentication on my Ruby on Rails application.

**Signing up for a Google Developer's Account**

First step to implementing google authentication is to get a developer account on their website. Give them necessary the necessary sign up information and once you successfully sign up, you should be redirected to a homepage. Once you get to this page, you should see a credentials page on the toolbar to the left. Click on it, and navigate to this page.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/uz753467rpact9wlrcx8.PNG)

When you get to the page, you should click on the create credentials button at the top of the page. Select the Oauth option for your authentication needs. You'll notice there are other goodies like the API keys, which you can use for a lot of Google's amazing (and expensive) API services. 

Once you create the Oauth credential keys, you should get to this page. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xsf9y3s2657qd7n6pwxo.PNG)

Here you need to give your client proper callback urls, which will get access to google's authentication information. Once your app does the typical google authentication requests, your application will need to get back some information, and these urls are the ones that are authorized to receive. You'll notice that there are two different types of urls available, Javascript origins and redirect URIs. The first is for client urls and the second one is for server urls. 

After finishing this, you need to format the authentication screen. You'll need to click the oauth consent screen on the toolbar, and get to this page. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/qrrjgwxqiyh9eev7o2vp.PNG)

Once you're here you'll need to name your app, and determine what scope you want to use, which determines how much of the user's information you'll be able to access. You'll also have to give it a name which your consent screen will display. 

**Rails Setup w/ OmniAuth**

For integrating your Google authentication on your Rails application, you'll first need to include the omniauth gem for google auth. Add `gem 'omniauth-google-oauth2'` to your Gemfile then run `bundle install`. 

*Intializer*

Now that you have your gems, let's first start with our environment. In Rails, to set up your environment, you'll need to use your intializers, which are the first things to run in your project file. Create a separate file in the intializers folder and add in this code. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/d7mcbgwa68jjay8e9z3z.PNG)

The ENV is referencing the client ID and secret from the client page where you included certain URI's. You'll have to include these somewhere in your Rails application. The way I did it was to include it in an `.env` at the root of the folder, and then assigned their keys to their respective values. Make sure to include your keys in the gitignore file to not hide them from public view.

Once you do this, you should be able to go to your `ROOT_URL + /auth/google_oauth2` which will give you the authentication screen from Google. You can now use this screen to try and sign in to your application with your Google account. 

*Routes*

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/01l2cuupss8gy2crsojn.PNG)

After you implement your consent screen, you'll need to have a callback route for the Rails server to handle the information that we'll get back from Google on authentication. The convention for these routes are given as you can see here. The callback route for handling the Google info returned will be named `auth/google_oauth2/callback`, and the case for failure will be named `auth/failure`. Notice the callback is routed to a sessions controller, where we'll handle creation of a session.

*Sessions*

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/g5bngo48ei0cd3nnbh1v.PNG)

First thing that we should notice is we're getting info back contained in the request variable, which has access tokens from our omniauth request. With the access token we'll run the method we will create in our user (shopper) model. With the id of our newly created shopper as the key, we can now create a session for the user. After creating the session, we'll save a token from Google in case we want to access any more user information in the future, and then save that user. 

*Model*

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/twg8i78qhdqy5mrwa850.PNG)

Here we have our shopper model. The method you see here is responsible for checking the email we received on our authorization callback and seeing if that email already exists in our database. If we already have a matching email, it will simply select that user. Otherwise, we will create the user with the given configuration using the information from the google callback, which will be returned as the shopper variable in our sessions controller. 

*OmniAuth requires session*

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ukdo8mt06rchanfptlmg.PNG)

Up to this point, I had followed the documentation and various tuotorials, but I had been continuing to get this error where it said that we weren't providing the omniauth gem with any session. This was strange since we clearly were creating a session in our session controller. The issue per a stack overflow post seemed to have been with some middleware configuration where we didn't store the session that we had created. In order to fix this we had to add middleware for cookies and storing those cookies, along with `insert_after` in order to place the middleware in the correct spot. After this code, everything seemed to be running smoothly.

**Success!**

After all of that we finally got our first user created!

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/w8pdqlxjq1wzp17814zk.PNG)

It's my data!

**Next Steps**

As I continue to work on my project still have some things to figure out: 

- connecting my frontend to trigger the callback on the backend
- ensuring the browser is getting the cookie/session id on the frontend to correctly handle authentication
- confirm that multiple sessions can be held at the same time.

Hope to come up with an edit to this article or an update soon. Until next time!