Update for OmniAuth Usage in Rails

Seth Blanchard
3 min readMar 21, 2021

One of the more difficult portions for the Rails project build for me was navigating and implementing OmniAuth to enable third-party login. I was directed to Rachel Hawa’s description, which was extremely helpful. The link is below.

https://medium.com/swlh/google-authentication-strategy-for-rails-5-application-cd37947d2b1b

While much of what the author went through is still functional with current OmniAuth (as of March, 2021), I ran into a few problems and felt an update/addendum would be helpful for others to avoid some of the pitfalls I encountered.

Following the author’s guidance, I also decided to use Google as my third-party authenticator and her instructions were spot on for use of their developer’s console. I will skip discussion of this as it was fully functional as written.

First Update

While there were three gems listed in her description, OmniAuth now needs a fourth, and the order matters for some of them.

gem 'dotenv-rails'gem 'omniauth-google-oauth2'gem 'omniauth-rails_csrf_protection'gem 'omniauth'

The dotenv gem needs to fire prior to Omniauth. Also, the CSRF Protection addition was not needed until recently.

Mistakes were made

The previous OmniAuth guide mentioned this, but it wasn’t HUGE, EMBOLDENED, and blinking… It’s still my fault for not reading carefully and not thinking about the consequences. Don’t be like me. Read carefully and follow ALL of the instructions. Once you create your .env file…

ADD THE .ENV FILE TO YOUR .GITIGNORE

If you don’t, you will at best get an automated email (mine came from Github) saying that they noticed there were public keys added to your account. I believe some third party development tools will revoke your secret at that point and you will have to start again.

Second Update

The next update I would like to discuss is the .erb tag file link instructions. This was probably the biggest issue I had with implementation as all of the directions I found prior to hadn’t worked for me and I kept getting an error. There is nothing more frustrating that following a how-to exactly as written/watched and then getting different results!

As written, the original article mentioned to use:

<%= link_to "Log In with Google", '/auth/google_oauth2' %>

I added the proper routes, class method in User, methods in the sessions controller, and then threw in the links where I wanted them to be. I was so excited to have this portion finished! Then came the error message…

This issue will be fixed by adding a third argument to your link, which forces the ‘post’ action, like so…

<%= link_to("Log In with Google", '/auth/google_oauth2', method: :post)%>

Final Thoughts/Change of behavior for different preferences

Once these changes have been implemented, your OmniAuth should be working, as expected. However, there was something in the mechanism for this set up that didn’t work the way I would have preferred. When I think about “Logging In” a user, that user should already be in my database, or else they have to go through my creation process. That way, if there is data I want them to have provided during the sign up process, it can be captured then.

def self.from_omniauth(auth)
where(email: auth.info.email).first_or_initialize do |user|
user.user_name = auth.info.name
user.email = auth.info.email
user.password = SecureRandom.hex
end
end

This was the original class method. As you can see, if the email being used through the third party can’t be located in the database, a new user will be “initialized” or instantiated.

This disallows a User to be required to add additional data upon instantiation and a developer has to then redirect them to manually add this information at a later time. I didn’t like the functionality of that and wanted them to just be redirected to the signup page if their email wasn’t already in the system.

def self.from_omniauth(auth)
where(email: auth.info.email).first do |user|
user.user_name = auth.info.name
user.email = auth.info.email
user.password = SecureRandom.hex
end
end

Simply removing the “_initialize” and then redirecting if the email can’t be located solved this problem for me.

--

--

Seth Blanchard
0 Followers

Full-Stack Software Developer- Founder of Skylark Hammocks, BEST, LLC, and several other as of yet unrealized ventures.