Using Google OAuth in Ruby on Rails Sites
OAuth allows the user to securely share data from provider sites (in this case google) to consumer sites (in this case your ruby on rails site). You can use OAuth to authenticate users or consume API’s on their behalf. Here we will have a look at both.
- Register your website with Google at https://www.google.com/accounts/ManageDomains. Replace example.com with your domain name
- Create a pair of RSA keys. In linux and OS X you can use openssl
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj ‘/C=US/ST=CA/L=San Francisco/CN=example.com’ -keyout rsakey.pem -out rsacert.pem - Use the just created rsacert.pem in the registration page. rsacert.pem and rsakey.pem can be placed in the config directory
- Note down the consumer key and consumer secret.
- Create a pair of RSA keys. In linux and OS X you can use openssl
- Install the latest oauth-ruby gem.(Right now 0.3.1.8) Do
sudo gem install mojodna-oauth - Create a User model
ruby script/generate model user name:string oauth_token:string oauth_secret:string email:stringclass User < ActiveRecord::Base validates_presence_of :email, :oauth_token, :oauth_secret validates_uniqueness_of :email end
You can also have the google oauth authenticaion co-exist with your existing user,password authentication mechanism if needed. In that case you can re-use your existing user model.
- In your application.rb add the following
def login_required if session[:user_id] @user ||= User.find(session[:user_id]) @access_token ||= OAuth::AccessToken.new(get_consumer, @user.oauth_token, @user.oauth_secret) else redirect_to :controller => 'session', :action => 'new' end end def get_consumer require 'oauth/consumer' require 'oauth/signature/rsa/sha1' consumer = OAuth::Consumer.new(CONSUMER_KEY,CONSUMER_SECRET, { :site => "https://www.google.com", :request_token_path => "/accounts/OAuthGetRequestToken", :access_token_path => "/accounts/OAuthGetAccessToken", :authorize_path=> "/accounts/OAuthAuthorizeToken", :signature_method => "RSA-SHA1", :private_key_file => PATH_TO_PRIVATE_KEY}) end
Replace CONSUMER_KEY,CONSUMER_SECRET and PATH_TO_PRIVATE_KEY with the appropriate values.
- Create a new session controller
class SessionController < ApplicationController skip_before_filter :login_required, :only => [:new, :create] def new consumer = get_consumer request_token = consumer.get_request_token( {}, {:scope => "https://www.google.com/m8/feeds/"}) session[:oauth_secret] = request_token.secret next_url = http://localhost:3000/session/create redirect_to request_token.authorize_url + "&oauth_callback=#{next_url}" end def create request_token = OAuth::RequestToken.new(get_consumer, params[:oauth_token], session[:oauth_secret]) access_token = request_token.get_access_token xml = XmlSimple.xml_in(access_token.get("https://www.google.com/m8/feeds/contacts/default/full/").body) email = xml["author"].first["email"].first user = User.find_or_create_by_email(email) user.name = xml["author"].first["name"].first user.oauth_token = access_token.token user.oauth_secret = access_token.secret user.save session[:user_id] = user.id redirect_to :controller => 'account' end def delete reset_session flash[:notice] = "You have been logged out" redirect_to :action => 'new' end end
Change next_url if needed. As per the convention, if the user needs to be authenticated he needs to be directed at the /session/new URL. The user will then be redirected to the google authentication page where they first need to log in using their google credentials (if not logged in elsewhere) and grant access to your application. If the user grants permission, then the user is redirected to the URL specified by oauth_callback. (Change next_url as needed). In this code, the user is now redirected to the create method where a request token is first instantiated and then upgraded to an access token.
The access token is valid for 24 hours and you can use it to make API calls on behalf of the user. The APIs you can consumer are limited by the scope parameter in consumer.get_request_token call. After receiving the access token we will make a call to the google contacts API to extract the user’s name and email address.
- On successful authentication, the create method will redirect the user to the account controller. You might want to create it or use some thing else.
Notes
- The scope and the API should have identical resource types i.e both should be http or https. Mixing http and https will likely result in errors.
- Don’t try to store the access_token or request_token object directly in a session. This can sometimes result in errors. Store the token and secret values in session and recreate the Access/Request Tokens from those values








Great post! Thanks for sharing this info!
I had OAuth working fine with Twitter, but getting it to work with Google was a little trickier.. Your notes helped a lot, thanks!
Thanks for the info, this helped me a lot.
Any info on posting to google with ruby oauth?
Leave a comment