CSC/ECE 517 Fall 2013/ch1 1w19 rj: Difference between revisions
Line 16: | Line 16: | ||
=== OAuth Consumer support === | === OAuth Consumer support === | ||
The oauth-plugin can generate an OAuth Consumer which includes a controller to manage the authentication flow between your application and any number of external OAuth secured applications that you wish to connect to | |||
== Creating a sample OAuth Application == | == Creating a sample OAuth Application == |
Revision as of 20:37, 16 September 2013
Using secure API authorization via OAuth
OAuth is the de facto standard authentication mechanism used by prominent websites like Facebook and Twitter. This wiki discusses Ruby support for OAuth and highlight using examples.
Introduction to OAuth
OAuth in Ruby
Ruby has several gems for turning your web application into an OAuth Provider or OAuth Consumer. The most popular, of course, is oauth
. However, this is NOT a Rails plugin, but could easily be used for the foundation for such a Rails plugin. As a matter of fact it has been pulled out from an oauth-plugin
which now requires this GEM [Source]. Some documentation on the oauth
gem is available at it's canonical GitHub repository.
OAuth Provider support
The oauth-plugin
can generate an OAuth Provider that supports the following out of the box:
- User can register their own applications to receive consumer key/secret pairs.
- Provider supports standard best practises out of the box hmac-sha1, etc.
- Users can manage and revoke tokens issued in their name
- Easy before filter to provide OAuth protection on your actions
OAuth Consumer support
The oauth-plugin can generate an OAuth Consumer which includes a controller to manage the authentication flow between your application and any number of external OAuth secured applications that you wish to connect to
Creating a sample OAuth Application
TODO: Add Ruby/Rails version used
Creating an OAuth Provider
Following steps will create a basic Rails application that uses OAuth to authenticate the requests.
1. Create a Rails application and remove public/index.html
rails new OAuthProviderApp
2. Add devise
, oauth-plugin
and dynamic_form
gems to your Gemfile
gem 'dynamic_form' gem 'devise' gem 'oauth-plugin'
3. Run bundle install
to install the Gems
bundle install
4. Run the devise:install
and devise User
generators to generate the User model, controller and views
rails generate devise:install rails generate devise User
The above commands generates the migration and model for User
.
5. Run the oauth_provider
generator
rails generate oauth_provider
This will generate the migrations, models, controllers, views and routes for the following:
- OAuthToken or AccessToken - The token used to associate the request with the resource owner.
- ClientApplication - Client application that needs access to the services offered by the Server on behalf of the Resource owner
- OAuthNonce - Used for verifying requests from the client
6. Migrate the database to create tables for User, OAuthToken, ClientApplication, and OAuthNonce in the database
rake db:migrate
7. To test the application, add the following route to your config/routes.rb
root :to => 'oauth_clients#index'
Thus, the home page will display the list of OAuth clients registered by a user (developer of OAuth client).
8. Add ClientApplication and OAuthToken associations to User model (app/models/user.rb
)
has_many :client_applications has_many :tokens, :class_name => 'Oauth2Token', :order => 'authorized_at desc', :include=>[:client_application]
9. Add the following accessors to the corresponding models
attr_accessible :user, :client_application # Add this to AccessToken attr_accessible :nonce, :password, :timestamp # Add this to OauthNonce attr_accessible :callback_url, :client_application # Add this to RequestToken attr_accessible :user, :client_application, :scope # Add this to Oauth2Token attr_accessible :client_application, :user, :scope, :callback_url # Add this to Oauth2Verifier attr_accessible :name, :url, :callback_url, :support_url # Add this to ClientApplication
This is required since the generator for oauth_provider
is outdated.
10. Add the following alias to app/controllers/oauth_controller.rb
and app/controllers/oauth_clients_controller.rb
after the class declaration
alias :login_required :authenticate_user!
This is required because oauth-plugin
uses login_required
method to determine whether the user is authenticated or not. In order to determine whether the user is authenticated or not, we use the authenticate_user!
method provided by devise
gem.
11. Add the following filter to config/application.rb
require 'oauth/rack/oauth_filter' #Add before declaration of module OAuthProviderApp config.middleware.use OAuth::Rack::OAuthFilter #Add after declaration of class Application
This adds the OAuthFilter to the middleware layer and thus allows filtering out unauthorized calls.
12. Add the following method to app/controllers/application_controller.rb
def current_user=(user) current_user = user end
This method is required by oauth-plugin
to let devise
know who the user is.
13. Generate a new controller that will define the services provided by the this provider
rails generate controller API::V1::Data
14. Add a dummy service method to this controller and have it render some response. This will be the service that the OAuth client will try to access.
class Api::V1::DataController respond_to :json, :xml oauthenticate :interactive=>false # Actions in this controller can only be accessed via OAuth def show # This is the service OAuth client will call respond_with 'My birthday is on 09/05/2013' end end
15. Add the following to config/routes.rb
namespace :api do namespace :v1 do match "show" => "data#show" end end
Creating an OAuth Consumer
Following steps will create a basic Rails application that uses OAuth to access customer's data (birth date) from an OAuth provider.
1. Create a Rails application and remove public/index.html
rails new OAuthConsumerApp
2. Add devise
and oauth-plugin
gems to your Gemfile
gem 'devise' gem 'oauth-plugin'
3. Run bundle install
to install the Gems
bundle install
4. Run the devise:install
and devise User
generators to generate the User model, controller and views
rails generate devise:install rails generate devise User
The above commands generates the migration and model for User
.
5. Run the oauth_consumer
generator
rails generate oauth_consumer user
This will generate the migrations, models, controllers and routes for ConsumerToken which is used by this Consumer to authenticate with the Provider.
6. Migrate the database to create tables for User and ConsumerToken
rake db:migrate
7. Add the following alias to app/controllers/oauth_consumers_controller.rb
after the class declaration
alias :login_required :authenticate_user!
This is required because oauth-plugin uses login_required method to determine whether the user is authenticated or not. In order to determine whether the user is authenticated or not, we use the authenticate_user! method provided by devise gem.
8. Add the following method to app/controllers/application_controller.rb
def current_user=(user) current_user = user end
This method is required by oauth-plugin
to let devise
know who the user is.
9. Create a new model that subclasses ConsumerToken for the above OAuthProvider service
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
The purpose of this subclass is to define the consumer
method that is based on the Provider.
10. Add the following to config/initializers/oauth_consumers.rb
defining the Consumer key and secret provided by the OAuthProviderApp
OAUTH_CREDENTIALS={ :test =>{ :key => "CRcIJ15MwSqlDTxsH8MpO3En4wjaOxkqeofLioH4", :secret => "C7uci8xkyMShCf4SNXWPclKbBo3ml1Zf2W2XWu4W", :expose => true } }
11. Generate a controller for testing the application
rails generate controller welcome index
12. Add logic to a controller action that performs the OAuth workflow as discussed in Introduction
def index @consumer_tokens = TestToken.all :conditions => {:user_id => current_user.id} @token = @consumer_tokens.first.client render inline: @token.get("/api/v1/data").body end
13. Add the following route to config/routes.rb
root :to => 'welcome#index'