Monthly Archives: April 2012

OAuth 1 and 2 (for Google) with OmniAuth1+2 Gems

OAuth is an important standard for cross domain authentication, allowing web apps and users to share subscriptions. Per wikipedia (http://en.wikipedia.org/wiki/Oauth), sites are supporting either 1.0 or 2.0 Oauth standards.

Service Provider OAuth Protocol
VK 2.0
Facebook 2.0
Foursquare 2.0
github 2.0
Google 2.0 + 1.0 + AuthSub
Microsoft (Hotmail, Messenger, Xbox) 2.0
LinkedIn 2.0
MySpace 1.0a
Netflix 1.0a
StatusNet 1.0a
Twitter 1.0a
Vimeo 1.0a
Yahoo! 1.0a

Google actually support 3 different authentication mechanisms.

  1. AuthSub – The legacy channel subscription mechanism of the YouTube,
  2. OAuth 1.0 – But, it only works for Google Contacts, I was NOT able to authenticate against YouTube with scope (http://gdata.youtube.com), even though it was documented in http://hoisie.com/2011/09/12/using-google-oauth-with-omniauth/  using omniauth + omniauth-google gems
  3. OAuth 2.0 – I was able to successfully authenticate against it using omniauth-oauth2 + omniauth-google-oauth2 gems

Note the following:

https://accounts.google.com/ManageDomains -> for OAuth 1.0
https://code.google.com/apis/console -> OAuth2 (This is the right one for YouTube Oauth 2)
https://www.google.com/a/cpanel/[mydomain]/SetupOAuth -> Service to Your Google App admin, i.e. Gmail, Calendar, etc.

You can then $ curl https://gdata.youtube.com/feeds/api/users/default -H ‘Authorization: OAuth ya29.reset of the Key’

I made an example Rails application, showing how to authenticate using those (oauth 1.0 and oauth 2.0) standards.

In the Rails application, following files are needed.

### Rails_root/Gemfile ###

source 'https://rubygems.org'

...
#OAuth 1.0
gem 'omniauth'
gem 'omniauth-google'

#OAuth 2.0
gem 'omniauth-oauth2'
gem 'omniauth-google-oauth2'
...

 

### routes.rb ###
<App name>::Application.routes.draw do
 resources :users

root :to => 'users#index'
 match "/auth/:provider/callback" => "sessions#create"
 match "/auth/failure" => "sessions#failure"
 match "/signout" => "sessions#destroy", :as => :signout
end

### config/initializers/omniauth.rb ###

OmniAuth.config.full_host = "http://localhost:3000"

Rails.application.config.middleware.use OmniAuth::Builder do
 # OAuth 1.0 result # Access token starts with 1/xxxx
#Get Oauth 1.0 Key (domain name format) + Consumer Secret from https://accounts.google.com/ManageDomains

 # Provider     Uid                                 Access Token                                     Secret
 # google        raygao@are4.us       1/---------oauth 1 token-------       XXXXXX
 provider :google, '<key in Dname>', '<Consumer Secret>', :scope => 'http://gdata.youtube.com'

# OAuth 2.0 result, # Access token starts with ya29.xxxx
 # get it from https://code.google.com/apis/console/
 # See https://github.com/zquestz/omniauth-google-oauth2/issues/20
 # This explain OAuth2 for Google. Note, OAuth, does not return token_secret.
 #     Provider                 Uid Access        Token                   Secret
 #    google_oauth2   102425343454127939656   ya29.<rest of the stuff>    <none>
 provider :google_oauth2, '<Client ID>.apps.googleusercontent.com', '<Client Secret>', {:access_type => 'online', :approval_prompt => '', :client_id => '<domain name>'}
end

 

### sessions_controller.rb ####</pre>
require 'pp'
class SessionsController < ApplicationController
 def create
 auth = request.env["omniauth.auth"]
 puts auth
 #user = User.find_by_provider_and_uid(auth["provider"], auth["uid"]) || User.create_with_omniauth(auth)
 user = User.create_with_omniauth(auth)
 session[:user_id] = user.id
 puts '###### Callback invoked #####'
 redirect_to root_url, :notice => "Signed in!"
 end

def destroy
 session[:user_id] = nil
 redirect_to root_url, :notice => "Signed out!"
 end

def failure
 #render :text => 'Google auth failed.'
 render :text => request.env['omniauth.auth'].to_hash.inspect rescue "No Data"
 end
end


###users/index.html.erb ###

<h1>Listing users</h1>

<table>
 <tr>
 <th>Provider</th>
 <th>Uid</th>
 <th>Access Token</th>
 <th>Secret</th>
 <th></th>
 <th></th>
 <th></th>
 </tr>

<% @users.each do |user| %>
 <tr>
 <td><%= user.provider %></td>
 <td><%= user.uid %></td>
 <td><%= user.access_token %></td>
 <td><%= user.secret %></td>
 <td><%= link_to 'Show', user %></td>
 <td><%= link_to 'Edit', edit_user_path(user) %></td>
 <td><%= link_to 'Destroy', user, :confirm => 'Are you sure?', :method => :delete %></td>
 </tr>
<% end %>
</table>

<br />

<%= link_to 'New User', new_user_path %>
<br/><hr/>
<%= link_to 'Google Auth', "/auth/google" %><br/>
<%= link_to 'Google OAuth 2', "/auth/google_oauth2" %><br/>
<hr/>
curl https://gdata.youtube.com/feeds/api/users/default -H 'Authorization: OAuth ya29.<long stuff>'
<br/>
note, Oauth2 has no return secret!!!
<br/>
Setup Oauth2 here -> https://code.google.com/apis/console

generate oauth 2.0 key for Google apps


### models/user.rb ###

class User < ActiveRecord::Base
 def self.create_with_omniauth(auth)
 u = User.new()
 u.provider = auth['provider']
 u.uid = auth['uid']
 u.access_token = auth['credentials']['token']
 u.secret = auth['credentials']['secret']
 puts "*" *80
 puts auth
 puts "*" *80
 u.save
 return u
 end
end

Google Oauth 1.0 + 2.0 results

The Zip file of the app is here ->  Utube

Enjoy!!!