vidibus-oauth2_server 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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