vidibus-oauth2_server 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,8 +1,8 @@
1
- = vidibus-oauth2_server
1
+ = Vidibus::Oauth2Server
2
2
 
3
- Allows OAuth2 authentication based on http://tools.ietf.org/html/draft-ietf-oauth2-v2-00.
3
+ Allows OAuth2 authentication for Rails applications based on http://tools.ietf.org/html/draft-ietf-oauth2-v2-00.
4
4
 
5
- This gem is part of the open source SOA framework Vidibus: http://vidibus.org.
5
+ This gem is part of the open source SOA framework {Vidibus}[http://vidibus.org].
6
6
 
7
7
  It is far from being complete and stable! But this will change soon.
8
8
 
@@ -15,44 +15,53 @@ Add the dependency to the Gemfile of your application:
15
15
 
16
16
  Then call bundle install on your console.
17
17
 
18
+ To get your own OAuth2 server working, some small adjustments will have to be made to your Rails application:
18
19
 
19
- === Routes
20
-
21
- Two routes will be added to your application. If you use a catch-all route, you will have to define these routes manually:
22
20
 
23
- get "oauth/authorize" => "oauth2#authorize"
24
- post "oauth/access_token" => "oauth2#access_token"
21
+ === Client model
25
22
 
23
+ Each remote application that requests authentication has to be authorized to do this. Usually, such an application will have to provide an API key that will be validated against a local repository. For OAuth2 this API key is called "client_id".
26
24
 
27
- === ApplicationController
25
+ Additionally, each client application has to provide a password to make a valid Oauth2 request, the "client_secret".
28
26
 
29
- In ApplicationController of your OAuth server application you have to define two methods in order to perform OAuth authentication.
27
+ This gem will validate an incoming OAuth2 request against client_id and client_secret parameters. Thus your client model has to provide both attributes, although they don't have to be named like this.
30
28
 
31
- The first method performs a sign in of the current user. If you use Devise for authentication, this method already exists and works. This is an example that works with Authlogic:
29
+ You'll also have to provide a #domain method on your OAuth client model that returns the domain name of the client, e.g. vidibus.org. This method is used to validate the redirect_url parameter.
32
30
 
33
- # Calls authentication method.
34
- def authenticate_user!
35
- logged_in? or login_required
36
- end
31
+ Before issuing a token, the Oauth2Controller will ensure that the given client_secret is valid. In order to perform this validation, a method #valid_oauth2_secret? must be given on your client model.
37
32
 
38
- The second method returns a client object with given id. This is an example for usage with vidibus-service gem:
33
+ If you use the {Vidibus::Service}[https://github.com/vidibus/vidibus-service] gem, you'll get this method on the service model:
39
34
 
40
- # Returns Service with given id.
41
- # This method is called from Vidibus' OauthServer gem.
42
- # The given client_id comprises the requesting service's
43
- # uuid and realm, concatenated by -
44
- def oauth2_client(client_id)
45
- Service(*client_id.split("-"))
35
+ # Returns true if given client_secret matches signature.
36
+ def valid_oauth2_secret?(client_secret)
37
+ client_secret == Vidibus::Secure.sign("#{Service.this.url}#{uuid}", secret)
46
38
  end
47
39
 
48
40
 
49
41
  === User model
50
42
 
51
- Your user model has to provide an unique UUID. If you use Mongoid, add the following:
43
+ Your user model has to provide an unique UUID in compact format. If you use Mongoid, you may include the UUID generator provided by the {Vidibus::Uuid}[https://github.com/vidibus/vidibus-uuid] gem:
52
44
 
53
- field :uuid
45
+ class User
46
+ include Mongoid::Document
47
+ include Vidibus::Uuid::Mongoid
48
+ ...
49
+ end
54
50
 
55
- If you have an ActiveRecord model, add a migration like this:
51
+ If you have an ActiveRecord model, implement something like this:
52
+
53
+ require "uuid"
54
+ class User < ActiveRecord::Base
55
+ before_create :generate_uuid
56
+ ...
57
+ protected
58
+
59
+ def generate_uuid
60
+ self.uuid ||= UUID.new.generate(:compact)
61
+ end
62
+ end
63
+
64
+ And don't forget the migration:
56
65
 
57
66
  require "uuid"
58
67
  class AddUuidToUsers < ActiveRecord::Migration
@@ -71,9 +80,44 @@ If you have an ActiveRecord model, add a migration like this:
71
80
  end
72
81
 
73
82
 
74
- === User controller
83
+ === Routes
84
+
85
+ Two routes will be added to your Rails application. If you use a catch-all route, you will have to define these routes manually:
75
86
 
76
- This gem will an action to obtain data of the currently logged in user. The following route will be added:
87
+ get "oauth/authorize" => "oauth2#authorize"
88
+ post "oauth/access_token" => "oauth2#access_token"
89
+
90
+
91
+ === ApplicationController
92
+
93
+ In the ApplicationController of your OAuth server application you'll have to define two methods in order to perform OAuth authentication.
94
+
95
+ The first method performs the sign-in of the current user. If you use Devise for authentication with a "User" model, that method already exists and works. This is an example that works with Authlogic:
96
+
97
+ # Calls authentication method.
98
+ def authenticate_user!
99
+ logged_in? or login_required
100
+ end
101
+
102
+ The second method returns a service client with given id. This is an example taken from the {Vidibus::Service}[https://github.com/vidibus/vidibus-service] gem:
103
+
104
+ # Returns service matching given client_id.
105
+ # This method is called from Vidibus' Oauth2Server gem.
106
+ #
107
+ # In this example from Vidibus the given client_id
108
+ # comprises the requesting service's uuid and realm,
109
+ # concatenated by -.
110
+ #
111
+ # Adjust this method to your needs.
112
+ #
113
+ def oauth2_client(client_id)
114
+ Service(*client_id.split("-"))
115
+ end
116
+
117
+
118
+ === Oauth2::UsersController
119
+
120
+ This gem will also provide an action to obtain data of the user currently logged in. The following route will be added:
77
121
 
78
122
  get "/oauth/user" => "oauth2/users#show"
79
123
 
@@ -86,31 +130,22 @@ For a typical ActiveRecord model this would be:
86
130
  User.first(:conditions => {:uuid => uuid})
87
131
  end
88
132
 
89
- The default #show method delivers a JSON string including name, email and UUID of the current user:
133
+ The default #show method of this controller delivers a JSON string including name, email and UUID of the current user:
90
134
 
91
135
  def show
92
136
  render :json => @user.attributes.only(*%w[name email uuid])
93
137
  end
94
138
 
139
+ == And the client side?
95
140
 
96
- === Client model
97
-
98
- Provide a #domain method to your OAuth client model that returns the domain name of the client. This method is used to validate the redirect_url.
141
+ Well, this is just the server side of the story. To implement OAuth2 on your client applications, there are many solutions available. The basic tools are provided by the excellent {OAuth2}[https://github.com/intridea/oauth2] gem. For a sophisticated example, check out {OmniAuth}[https://github.com/intridea/omniauth].
99
142
 
100
- Before issuing a token, the Oauth2Controller will ensure that the given client_secret is valid. In order to perform this validation, a method #valid_oauth2_secret? must be given on your client model.
101
-
102
- If you use the vidibus-service gem, you'll get this method on the service model:
103
-
104
- # Returns true if given client_secret matches signature.
105
- def valid_oauth2_secret?(client_secret)
106
- client_secret == Vidibus::Secure.sign("#{Service.this.url}#{uuid}", secret)
107
- end
143
+ In a typical Vidibus service-oriented environment, clients are equipped with the {Vidibus::User}[https://github.com/vidibus/vidibus-user] gem.
108
144
 
109
145
 
110
146
  == TODO
111
147
 
112
148
  * Write specs!
113
- * Explain usage and integration
114
149
  * Implement token expiry
115
150
  * Apply changes made in http://tools.ietf.org/html/draft-ietf-oauth2-v2-10?
116
151
 
data/Rakefile CHANGED
@@ -1,5 +1,8 @@
1
1
  require "rubygems"
2
2
  require "rake"
3
+ require "rake/rdoctask"
4
+ require "rspec"
5
+ require "rspec/core/rake_task"
3
6
 
4
7
  begin
5
8
  require "jeweler"
@@ -16,3 +19,18 @@ begin
16
19
  rescue LoadError
17
20
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
18
21
  end
22
+
23
+ Rspec::Core::RakeTask.new(:rcov) do |t|
24
+ t.pattern = "spec/**/*_spec.rb"
25
+ t.rcov = true
26
+ t.rcov_opts = ["--exclude", "^spec,/gems/"]
27
+ end
28
+
29
+ Rake::RDocTask.new do |rdoc|
30
+ version = File.exist?("VERSION") ? File.read("VERSION") : ""
31
+ rdoc.rdoc_dir = "rdoc"
32
+ rdoc.title = "vidibus-oauth2_server #{version}"
33
+ rdoc.rdoc_files.include("README*")
34
+ rdoc.rdoc_files.include("lib/**/*.rb")
35
+ rdoc.options << "--charset=utf-8"
36
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -1,102 +1,100 @@
1
- module Oauth2
2
- class AuthenticationController < ApplicationController
3
- skip_before_filter :verify_authenticity_token
1
+ class Oauth2::AuthenticationController < Oauth2Controller
2
+ skip_before_filter :verify_authenticity_token
4
3
 
5
- around_filter :oauth2_error_handler
4
+ around_filter :oauth2_error_handler
6
5
 
7
- before_filter :validate_oauth2_type!
8
- before_filter :validate_oauth2_client_id!
9
- before_filter :validate_oauth2_redirect_url!
6
+ before_filter :validate_oauth2_type!
7
+ before_filter :validate_oauth2_client_id!
8
+ before_filter :validate_oauth2_redirect_url!
10
9
 
11
- before_filter :authenticate_user!, :only => :authorize
12
- before_filter :validate_oauth2_client_secret!, :only => :access_token
10
+ before_filter :authenticate_user!, :only => :authorize
11
+ before_filter :validate_oauth2_client_secret!, :only => :access_token
13
12
 
14
- def authorize
15
- args = params.slice(:client_id, :redirect_url)
16
- args[:user_id] = current_user.uuid
17
- token = Oauth2Token.create!(args)
18
- uri_params = { :code => token.code }
19
- uri_params[:state] = params[:state] if params.has_key?(:state)
20
- uri = params[:redirect_url].with_params(uri_params)
21
- redirect_to(uri)
22
- end
13
+ def authorize
14
+ args = params.slice(:client_id, :redirect_url)
15
+ args[:user_id] = current_user.uuid
16
+ token = Oauth2Token.create!(args)
17
+ uri_params = { :code => token.code }
18
+ uri_params[:state] = params[:state] if params.has_key?(:state)
19
+ uri = params[:redirect_url].with_params(uri_params)
20
+ redirect_to(uri)
21
+ end
23
22
 
24
- def access_token
25
- token = Oauth2Token.find!(params)
26
- render :text => { :access_token => token.token }.to_uri, :type => :url_encoded_form, :status => :ok
27
- end
23
+ def access_token
24
+ token = Oauth2Token.find!(params)
25
+ render :text => { :access_token => token.token }.to_uri, :type => :url_encoded_form, :status => :ok
26
+ end
28
27
 
29
- protected
28
+ protected
30
29
 
31
- # Ensures that the type of flow is supported
32
- def validate_oauth2_type!
33
- type = params[:type]
34
- raise Vidibus::Oauth2Server::MissingTypeError if type.blank?
35
- raise Vidibus::Oauth2Server::UnsupportedTypeError unless Vidibus::Oauth2Server::FLOWS.include?(type)
36
- end
30
+ # Ensures that the type of flow is supported
31
+ def validate_oauth2_type!
32
+ type = params[:type]
33
+ raise Vidibus::Oauth2Server::MissingTypeError if type.blank?
34
+ raise Vidibus::Oauth2Server::UnsupportedTypeError unless Vidibus::Oauth2Server::FLOWS.include?(type)
35
+ end
37
36
 
38
- # Ensures that given client id is valid
39
- def validate_oauth2_client_id!
40
- raise Vidibus::Oauth2Server::MissingClientIdError if params[:client_id].blank?
41
- @oauth2_client = oauth2_client(params[:client_id])
42
- raise Vidibus::Oauth2Server::InvalidClientIdError unless @oauth2_client
43
- end
37
+ # Ensures that given client id is valid
38
+ def validate_oauth2_client_id!
39
+ raise Vidibus::Oauth2Server::MissingClientIdError if params[:client_id].blank?
40
+ @oauth2_client = oauth2_client(params[:client_id])
41
+ raise Vidibus::Oauth2Server::InvalidClientIdError unless @oauth2_client
42
+ end
44
43
 
45
- # Ensures that redirect_url is valid for given client.
46
- def validate_oauth2_redirect_url!
47
- redirect_url = params[:redirect_url]
48
- raise Vidibus::Oauth2Server::MissingRedirectUrlError if redirect_url.blank?
49
- raise Vidibus::Oauth2Server::MalformedRedirectUrlError unless valid_uri?(redirect_url)
50
- unless redirect_url.match(/^https?:\/\/([a-z0-9]+\.)?#{@oauth2_client.domain}/) # allow subdomains but ensure host of client application
51
- raise Vidibus::Oauth2Server::InvalidRedirectUrlError
52
- end
44
+ # Ensures that redirect_url is valid for given client.
45
+ def validate_oauth2_redirect_url!
46
+ redirect_url = params[:redirect_url]
47
+ raise Vidibus::Oauth2Server::MissingRedirectUrlError if redirect_url.blank?
48
+ raise Vidibus::Oauth2Server::MalformedRedirectUrlError unless valid_uri?(redirect_url)
49
+ unless redirect_url.match(/^https?:\/\/([a-z0-9]+\.)?#{@oauth2_client.domain}/) # allow subdomains but ensure host of client application
50
+ raise Vidibus::Oauth2Server::InvalidRedirectUrlError
53
51
  end
52
+ end
54
53
 
55
- # Ensures that given client_secret is valid for given client.
56
- def validate_oauth2_client_secret!
57
- raise Vidibus::Oauth2Server::InvalidClientSecretError unless @oauth2_client.valid_oauth2_secret?(params[:client_secret])
58
- end
54
+ # Ensures that given client_secret is valid for given client.
55
+ def validate_oauth2_client_secret!
56
+ raise Vidibus::Oauth2Server::InvalidClientSecretError unless @oauth2_client.valid_oauth2_secret?(params[:client_secret])
57
+ end
59
58
 
60
- # Returns error message for given exception.
61
- def oauth2_error_handler
62
- begin
63
- yield
64
- rescue Vidibus::Oauth2Server::MissingTypeError
65
- error = "missing_type"
66
- rescue Vidibus::Oauth2Server::UnsupportedTypeError
67
- error = "unsupported_type"
68
- rescue Vidibus::Oauth2Server::MissingClientIdError
69
- error = "missing_client_id"
70
- rescue Vidibus::Oauth2Server::InvalidClientIdError
71
- error = "invalid_client_id"
72
- rescue Vidibus::Oauth2Server::InvalidClientSecretError
73
- error = "invalid_client_secret"
74
- rescue Vidibus::Oauth2Server::MissingRedirectUrlError
75
- error = "missing_redirect_url"
76
- rescue Vidibus::Oauth2Server::MalformedRedirectUrlError
77
- error = "malformed_redirect_url"
78
- rescue Vidibus::Oauth2Server::InvalidRedirectUrlError
79
- error = "invalid_redirect_url"
80
- rescue Vidibus::Oauth2Server::MissingCodeError
81
- error = "missing_code"
82
- rescue Vidibus::Oauth2Server::InvalidCodeError
83
- error = "invalid_code"
84
- rescue Vidibus::Oauth2Server::ExpiredCodeError
85
- error = "expired_code"
86
- rescue Vidibus::Oauth2Server::InvalidTokenError
87
- error = "invalid_token"
88
- rescue Vidibus::Oauth2Server::ExpiredTokenError
89
- error = "expired_token"
90
- ensure
91
- if error
92
- status ||= :bad_request
93
- render :text => I18n.t("oauth2_server.errors.#{error}"), :status => status
94
- end
59
+ # Returns error message for given exception.
60
+ def oauth2_error_handler
61
+ begin
62
+ yield
63
+ rescue Vidibus::Oauth2Server::MissingTypeError
64
+ error = "missing_type"
65
+ rescue Vidibus::Oauth2Server::UnsupportedTypeError
66
+ error = "unsupported_type"
67
+ rescue Vidibus::Oauth2Server::MissingClientIdError
68
+ error = "missing_client_id"
69
+ rescue Vidibus::Oauth2Server::InvalidClientIdError
70
+ error = "invalid_client_id"
71
+ rescue Vidibus::Oauth2Server::InvalidClientSecretError
72
+ error = "invalid_client_secret"
73
+ rescue Vidibus::Oauth2Server::MissingRedirectUrlError
74
+ error = "missing_redirect_url"
75
+ rescue Vidibus::Oauth2Server::MalformedRedirectUrlError
76
+ error = "malformed_redirect_url"
77
+ rescue Vidibus::Oauth2Server::InvalidRedirectUrlError
78
+ error = "invalid_redirect_url"
79
+ rescue Vidibus::Oauth2Server::MissingCodeError
80
+ error = "missing_code"
81
+ rescue Vidibus::Oauth2Server::InvalidCodeError
82
+ error = "invalid_code"
83
+ rescue Vidibus::Oauth2Server::ExpiredCodeError
84
+ error = "expired_code"
85
+ rescue Vidibus::Oauth2Server::InvalidTokenError
86
+ error = "invalid_token"
87
+ rescue Vidibus::Oauth2Server::ExpiredTokenError
88
+ error = "expired_token"
89
+ ensure
90
+ if error
91
+ status ||= :bad_request
92
+ render :text => I18n.t("oauth2_server.errors.#{error}"), :status => status
95
93
  end
96
-
97
- # Autorization error?
98
- # :status => :unauthorized # The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource.
99
- # :status => :forbidden # Maybe better?
100
94
  end
95
+
96
+ # Autorization error?
97
+ # :status => :unauthorized # The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource.
98
+ # :status => :forbidden # Maybe better?
101
99
  end
102
100
  end
@@ -1,20 +1,18 @@
1
- module Oauth2
2
- class UsersController < ApplicationController
3
- before_filter :ensure_token!
4
- before_filter :find_user
1
+ class Oauth2::UsersController < Oauth2Controller
2
+ before_filter :ensure_token!
3
+ before_filter :find_user
5
4
 
6
- def show
7
- render :json => @user.attributes.only(*%w[name email uuid])
8
- end
5
+ def show
6
+ render :json => @user.attributes.only(*%w[name email uuid])
7
+ end
9
8
 
10
- protected
9
+ protected
11
10
 
12
- def find_user
13
- @user = find_user_by_uuid(@access_token.user_id) or render(:nothing => true, :status => :bad_request)
14
- end
11
+ def find_user
12
+ @user = find_user_by_uuid(@access_token.user_id) or render(:nothing => true, :status => :bad_request)
13
+ end
15
14
 
16
- def ensure_token!
17
- @access_token = Oauth2Token.find!(:token => params[:access_token])
18
- end
15
+ def ensure_token!
16
+ @access_token = Oauth2Token.find!(:token => params[:access_token])
19
17
  end
20
18
  end
@@ -0,0 +1,2 @@
1
+ class Oauth2Controller < ApplicationController
2
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{vidibus-oauth2_server}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andre Pankratz"]
12
- s.date = %q{2011-01-14}
12
+ s.date = %q{2011-02-23}
13
13
  s.description = %q{OAuth2 server for Rails 3 with Mongoid.}
14
14
  s.email = %q{andre@vidibus.com}
15
15
  s.extra_rdoc_files = [
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  "VERSION",
27
27
  "app/controllers/oauth2/authentication_controller.rb",
28
28
  "app/controllers/oauth2/users_controller.rb",
29
+ "app/controllers/oauth2_controller.rb",
29
30
  "app/models/oauth2_token.rb",
30
31
  "config/locales/en.yml",
31
32
  "config/routes.rb",
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vidibus-oauth2_server
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andre Pankratz
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-14 00:00:00 +01:00
18
+ date: 2011-02-23 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -189,6 +189,7 @@ files:
189
189
  - VERSION
190
190
  - app/controllers/oauth2/authentication_controller.rb
191
191
  - app/controllers/oauth2/users_controller.rb
192
+ - app/controllers/oauth2_controller.rb
192
193
  - app/models/oauth2_token.rb
193
194
  - config/locales/en.yml
194
195
  - config/routes.rb