This repo includes the demo use of oauth2 in rails, for both provider and client app.
As described in the spec:
OAuth provides a method for clients to access a protected resource on behalf of a resource owner. Before a client can access a protected resource, it must first obtain authorization from the resource owner, then exchange the access grant for an access token (representing the grant’s scope, duration, and other attributes). The client accesses the protected resource by presenting the access token to the resource server.
The most recent version is v0.10 , and most of the gems/plugins available is based on the v0.9 version of the spec.
And a abstract protocol flow is illustrated here: http://tools.ietf.org/html/draft-ietf-oauth-v2-09#section-1.3
Because the oauth2 protocol is pretty new itself, the gems/plugins are under development, and some of them are in alpha state and then not maintained anymore.
Below is a list of gems/plugins implemented oauth2.
oauth2_provider: https://github.com/ThoughtWorksStudios/oauth2_provider
oauth2-ruby: https://github.com/aflatter/oauth2-ruby
rack-oauth2-server: https://github.com/flowtown/rack-oauth2-server
OAuth2 https://github.com/intridea/oauth2
devise_oauth2_facebook https://github.com/mooktakim/devise_oauth2_facebook
authlogic_oauth2 https://github.com/andyhite/authlogic_oauth2
considering the stability and activity, we choose the “oauth2_provider” plugin for provider app and “oauth2” for client app.
Note: both plugins and gems are modified to compatible with the spec and work with each other.
There are 2 sample apps in the repo.
The blog app is a provider app, it provide the oauth2 authentication, you can register a client app and authenticate against it.
It also provide a UI to checkout registered clients.
here are the steps for setting up the provider app
- rake db:create
- rake db:seed
- start the application with ./script/server
- login with blogger/123456 create several articles
- click the “Clients” link on the top right
- create a client app and name it “publisher”, with Redirect uri: “http://localhost:4000/oauth/callback”
- when done, copy the Client id and Client secret for later use.
The publisher app is a client app, you can config the oauth2 authentication information there, and get protected resources from the provider
here are the steps for setting up the client app:
- go to the app/controllers/oauth_controller.rb, and replace the client_id and client_secret with the pair you got in setting up provider app
- rake db:create
- rake db:seed
- start server with ./script/server -p 4000
- click the “get articles!” link and login with publisher/123456
- when redirected to Blog app and asked for login, login with blogger/123456 on the Blog app
- make sure check the checkbox and click submit when ask for permission.
- then you should see the articles returned from the provider app
normally you just set up new project as described in the above section, just remember use the gem/plugin nested in the sample app.
below is the explanation of what have been changed in the gem/plugin and why.
You can follow the provider setting up instructino here: https://github.com/ThoughtWorksStudios/oauth2_provider
and remember use the plugin nested in the sample provider app, if not you may get the following exception
ArgumentError in Oauth2::provider::oauthauthorizeController#index
A copy of ApplicationController has been removed from the module tree but is still active!
def access_token_url(params = {})
path = options[:access_token_url] || options[:access_token_path] || "/oauth/access_token"
# according to http://tools.ietf.org/html/draft-ietf-oauth-v2-09#section-4.1.1
# :grant_type is required and should be set to authorization-code
params.merge!({:grant_type => "authorization-code"})
connection.build_url(path, params).to_s
end
def authorize_url(params = { :response_type => 'code' })
path = options[:authorize_url] || options[:authorize_path] || "/oauth/authorize"
# according to http://tools.ietf.org/html/draft-ietf-oauth-v2-09#section-3
# response_type is required
params.merge!({:response_type => 'code'})
connection.build_url(path, params).to_s
end