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.
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.
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.
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.
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
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
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
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
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!
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!
Top comments (4)
Does this work with API only version of the Rails app or not?
Thanks for a great tutorial ;D
Man I needed to see this blog thank you for posting!
Hi, did you have a code for frontend ? It's weird to use GET instead of POST no ?
Thx