Rails and oauth-plugin part 2: the consumer
In the previous post, I showed how you could build a provider with oauth-plugin and Rails. Now, I will demonstrate how to build a consumer (it’s a lot easier).
I will assume that your provider is already running on localhost:3000. The consumer will run on localhost:4000 (run it with “rails server -p 4000″).
Here we go!
rails new consumer cd consumer
Put this in your Gemfile:
source 'http://rubygems.org' gem 'rails', '3.0.7' gem 'sqlite3' gem 'devise' gem "oauth-plugin", ">= 0.4.0.pre1"
And run these commands:
bundle install rails generate devise:install rails generate devise User rake db:migrate rails generate controller welcome index rm public/index.html
And here is your routes.rb:
Provider::Application.routes.draw do devise_for :users root :to => "welcome#index" end
Create the consumer
rails generate oauth_consumer user rake db:migrate
in app/controllers/oauth_consumers_controller.rb, replace:
before_filter :login_required, :only=>:index
by
before_filter :authenticate_user!, :only=>:index
Uncomment the methods for devise (go_back, logged_in? currentuser=, deny_access!) in app/controllers/oauth_consumers_controller.rb.
Add to app/models/user.rb:
has_one :test, :class_name=>"TestToken", :dependent=>:destroy
Now go to http://localhost:3000/oauth_clients/ to register your first application with these parameters:
Name: Test consumer
Main Application URL: http://localhost:4000/
Callback URL: http://localhost:4000/oauth_consumers/test/callback
You’re redirected to http://localhost:3000/oauth_clients/1. It shows:
Consumer Key: CRcIJ15MwSqlDTxsH8MpO3En4wjaOxkqeofLioH4
Consumer Secret: C7uci8xkyMShCf4SNXWPclKbBo3ml1Zf2W2XWu4W
Request Token URL: http://localhost:3000/oauth/request_token
Access Token URL: http://localhost:3000/oauth/access_token
Authorize URL: http://localhost:3000/oauth/authorize
Now, you need to put the key and secret in config/initializers/oauth_consumers.rb:
OAUTH_CREDENTIALS={
:test =>{
:key => "CRcIJ15MwSqlDTxsH8MpO3En4wjaOxkqeofLioH4",
:secret => "C7uci8xkyMShCf4SNXWPclKbBo3ml1Zf2W2XWu4W",
:expose => true
}
}
Create app/models/test_token.rb. This model will store the token for your provider. If you want to provide helpful methods, take inspiration from lib/oauth/models/consumers/services/.
class TestToken < ConsumerToken
TEST_SETTINGS={
:site => "http://localhost:3000",
:request_token_path => "/oauth/request_token",
:access_token_path => "/oauth/access_token",
:authorize_path => "/oauth/authorize"
}
def self.consumer(options={})
@consumer ||= OAuth::Consumer.new(credentials[:key], credentials[:secret], TEST_SETTINGS.merge(options))
end
end
You should now be able to use the URLs “/oauth_consumers/test/client/”, “/oauth_consumers/test/callback”, “/oauth_consumers/test/callback2″,” /oauth_consumers/test/edit”,
and “/oauth_consumers/test”.
Modify the welcome controller t get the provider data:
class WelcomeController < ApplicationController
def index
# cf http://oauth.rubyforge.org/rdoc/classes/OAuth/AccessToken.html
@consumer_tokens=TestToken.all :conditions=>{:user_id=>current_user.id}
@token = @consumer_tokens.first.client
logger.info "private data: "+@token.get("/data/index").body
end
end
To connect a user to an external service link or redirect them to:
/oauth_consumers/[SERVICE_NAME]
Where SERVICE_NAME is the name you set in the OAUTH_CREDENTIALS hash. This will request the request token and redirect the user to the services authorization screen. When the user accepts the get redirected back to:
/oauth_consumers/[SERVICE_NAME]/callback
That’s it
This tutorial is really short, and could be explained a bit more, but I’ll leave that for another post. You have enough to start tinkering with OAuth. Have fun!
TEST_SETTINGS={
:site => “http://172.16.1.56″,
:request_token_path => “/oauth/request_token”,
:access_token_path => “/oauth/access_token”,
:authorize_path => “/oauth/authorize”
}
In the context of this tutorial I had to change
http://172.16.1.56
to
http://localhost:3000
Thank you, I fixed it. I tend to assume that readers will know how to adapt the configuration, but it’s better if it works out of the box.
Great post!
but I had some trouble here..
when the consumer authorize the test app.. and get redirected to the callback url.. the user / current_user ? is null.. so the consumer_token.user_id is null too..
I can’t figured out the problem.. please help
You should add this to your ApplicationController:
def current_user=(user)
current_user = user
end
Thanks for this info,
I was also having trouble with user and the consumer token not being created on the callback and I was receiving this error Validation failed: User can’t be blank. It worked once after I commented out the
before_create :create_user but every time now stil doesn’t create the user or consumer token and my log just says Completed 422 Unprocessable Entity.
Any ideas??
Thanks
I’m having the same problem here, and adding this to my ApplicationController doesn’t solve it.
I was also having the same issue, but found the solution here – https://github.com/pelle/oauth-plugin/issues/96.
The user_id is NULL when the consumer token is being saved due to a conflict, possibly with devise.
Hi Géal,
First of all, awesome two part post. This has been the most useful, and step by step Oauth tutorial I’ve found yet.
I am going through everything step by step, but I keep getting stuck trying to connect the consumer to the provider.
My steps:
1. Create provider/consumer as directed
2. Create a user account on provider, log in, and create a client
3. Add generated credentials to consumer
3. Create another user account on consumer, log in, and try to connect to the provider
As the consumer redirects to the provider to get authorization, i get the following error on the provider
– ArgumentError (wrong number of arguments (0 for 2))
But I can’t figure out where?
I have included the full error below.
Is there something obvious that you can help me see? If not, no worries, still a big thanks for the effort you put in write to the posts!
=======================================================================
Started GET “/oauth/authorize?oauth_token=LLPX0BFno7FhzBaDiJcSKTKr7thuobM1gjI78zU3″ for 127.0.0.1 at 2011-10-25 23:41:18 -0700
←[1m←[35mOauth2Token Load (0.0ms)←[0m SELECT “oauth_tokens”.* FROM “oauth_tokens” WHERE “oauth_tokens”.”type” = ‘Oauth2Token’ AND (invalidat
ed_at IS NULL AND authorized_at IS NOT NULL and token = ‘LLPX0BFno7FhzBaDiJcSKTKr7thuobM1gjI78zU3′) LIMIT 1
Processing by OauthController#authorize as HTML
Parameters: {“oauth_token”=>”LLPX0BFno7FhzBaDiJcSKTKr7thuobM1gjI78zU3″}
Completed in 1ms
ArgumentError (wrong number of arguments (0 for 2)):
Rendered c:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.7/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.0ms)
Rendered c:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.7/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.0ms
)
Rendered c:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.7/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/l
ayout (13.0ms)
Hello, see http://unhandledexpression.com/2011/06/02/rails-and-oauth-plugin-part-1-the-provider/#comment-243
There was a typo in the provider tutorial.
woo hoo!!! Thanks Géal!
I’m having a problem using the client endpoint for an oauth service when the format is specified.
I try to specify the return format using the following url:
http://consumer.dev/oauth_consumers/dupl/client/series.json
But Rails just json formats the returned *html* response, and doesn’t send the format as part of the endpoint.
from the consumer log:
Started GET “/oauth_consumers/dupl/client/series.json” for 127.0.0.1 at 2011-12-14 15:06:22 -0500
Processing by OauthConsumersController#client as JSON
Parameters: {“id”=>”dupl”, “endpoint”=>”series”}
and the client log:
Started GET “/series/” for 127.0.0.1 at 2011-12-14 15:06:22 -0500
am i missing something?
I don’t really get what you’re trying to do. Could you elaborate a bit? (like, who is the provider, who is the consumer, where is the data, and where do you make the call?)
Thanks for this pair of posts. Tremendously useful – you made it all a lot simpler than I’ve seen elsewhere and I got my provider/consumer up in a very short time.
Is there a zipped version of the rails app available? Would like to see it all in context and try out… If yes & you can provide this, can it run on the latest version of rails? (v3.2.1)
I could publish it, yes, but I have not tried it with Rails 3.2. I’ll try to push the actual code to Github.
Pardon me if the question is too naive.
I followed the tutorial completely till ” creating the app/models/test_token.rb” part. After that I was lost. We never wrote any migration for this model, yet we try to do @consumer_tokens=TestToken.all :conditions=>{:user_id=>current_user.id} in the welcome controller.
I tried doing
c = TestToken.new.client
c.get(“/services/blocked_ips.json”).body
but it gives me “Invalid OAuth Request”. can’t figure out what exactly i missed. Any help is appreciated.