oauth2-provider 0.0.16

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.
Files changed (101) hide show
  1. data/.gitignore +8 -0
  2. data/Gemfile +3 -0
  3. data/README.md +49 -0
  4. data/Rakefile +24 -0
  5. data/examples/client/Gemfile +6 -0
  6. data/examples/client/Gemfile.lock +20 -0
  7. data/examples/client/README +8 -0
  8. data/examples/client/app.rb +59 -0
  9. data/examples/client/config.ru +3 -0
  10. data/examples/client/views/home.haml +3 -0
  11. data/examples/client/views/response.haml +11 -0
  12. data/examples/rails3-example/.gitignore +4 -0
  13. data/examples/rails3-example/Gemfile +10 -0
  14. data/examples/rails3-example/Gemfile.lock +82 -0
  15. data/examples/rails3-example/README +9 -0
  16. data/examples/rails3-example/Rakefile +7 -0
  17. data/examples/rails3-example/app/controllers/account_controller.rb +14 -0
  18. data/examples/rails3-example/app/controllers/application_controller.rb +18 -0
  19. data/examples/rails3-example/app/controllers/authorization_controller.rb +18 -0
  20. data/examples/rails3-example/app/controllers/home_controller.rb +4 -0
  21. data/examples/rails3-example/app/controllers/session_controller.rb +24 -0
  22. data/examples/rails3-example/app/helpers/application_helper.rb +2 -0
  23. data/examples/rails3-example/app/models/account.rb +6 -0
  24. data/examples/rails3-example/app/views/authorization/new.html.erb +5 -0
  25. data/examples/rails3-example/app/views/home/show.html.erb +1 -0
  26. data/examples/rails3-example/app/views/layouts/application.html.erb +16 -0
  27. data/examples/rails3-example/app/views/session/new.html.erb +7 -0
  28. data/examples/rails3-example/config.ru +4 -0
  29. data/examples/rails3-example/config/application.rb +42 -0
  30. data/examples/rails3-example/config/boot.rb +6 -0
  31. data/examples/rails3-example/config/database.yml +22 -0
  32. data/examples/rails3-example/config/environment.rb +5 -0
  33. data/examples/rails3-example/config/environments/development.rb +26 -0
  34. data/examples/rails3-example/config/environments/production.rb +49 -0
  35. data/examples/rails3-example/config/environments/test.rb +35 -0
  36. data/examples/rails3-example/config/initializers/backtrace_silencers.rb +7 -0
  37. data/examples/rails3-example/config/initializers/inflections.rb +10 -0
  38. data/examples/rails3-example/config/initializers/mime_types.rb +5 -0
  39. data/examples/rails3-example/config/initializers/secret_token.rb +7 -0
  40. data/examples/rails3-example/config/initializers/session_store.rb +8 -0
  41. data/examples/rails3-example/config/locales/en.yml +5 -0
  42. data/examples/rails3-example/config/routes.rb +9 -0
  43. data/examples/rails3-example/db/migrate/20110508151935_add_account_table.rb +12 -0
  44. data/examples/rails3-example/db/migrate/20110508151948_add_oauth2_tables.rb +43 -0
  45. data/examples/rails3-example/db/schema.rb +52 -0
  46. data/examples/rails3-example/db/seeds.rb +11 -0
  47. data/examples/rails3-example/doc/README_FOR_APP +2 -0
  48. data/examples/rails3-example/lib/tasks/.gitkeep +0 -0
  49. data/examples/rails3-example/public/404.html +26 -0
  50. data/examples/rails3-example/public/422.html +26 -0
  51. data/examples/rails3-example/public/500.html +26 -0
  52. data/examples/rails3-example/public/favicon.ico +0 -0
  53. data/examples/rails3-example/public/images/rails.png +0 -0
  54. data/examples/rails3-example/public/robots.txt +5 -0
  55. data/examples/rails3-example/public/stylesheets/.gitkeep +0 -0
  56. data/examples/rails3-example/script/rails +6 -0
  57. data/lib/oauth2-provider.rb +3 -0
  58. data/lib/oauth2/provider.rb +39 -0
  59. data/lib/oauth2/provider/models.rb +40 -0
  60. data/lib/oauth2/provider/models/access_token.rb +54 -0
  61. data/lib/oauth2/provider/models/active_record.rb +30 -0
  62. data/lib/oauth2/provider/models/active_record/access_token.rb +13 -0
  63. data/lib/oauth2/provider/models/active_record/authorization.rb +16 -0
  64. data/lib/oauth2/provider/models/active_record/authorization_code.rb +13 -0
  65. data/lib/oauth2/provider/models/active_record/client.rb +15 -0
  66. data/lib/oauth2/provider/models/authorization.rb +40 -0
  67. data/lib/oauth2/provider/models/authorization_code.rb +27 -0
  68. data/lib/oauth2/provider/models/client.rb +28 -0
  69. data/lib/oauth2/provider/models/mongoid.rb +30 -0
  70. data/lib/oauth2/provider/models/mongoid/access_token.rb +40 -0
  71. data/lib/oauth2/provider/models/mongoid/authorization.rb +32 -0
  72. data/lib/oauth2/provider/models/mongoid/authorization_code.rb +43 -0
  73. data/lib/oauth2/provider/models/mongoid/client.rb +40 -0
  74. data/lib/oauth2/provider/rack.rb +11 -0
  75. data/lib/oauth2/provider/rack/access_token_handler.rb +103 -0
  76. data/lib/oauth2/provider/rack/authorization_code_request.rb +74 -0
  77. data/lib/oauth2/provider/rack/authorization_codes_support.rb +25 -0
  78. data/lib/oauth2/provider/rack/middleware.rb +28 -0
  79. data/lib/oauth2/provider/rack/resource_request.rb +91 -0
  80. data/lib/oauth2/provider/rack/responses.rb +34 -0
  81. data/lib/oauth2/provider/rails.rb +37 -0
  82. data/lib/oauth2/provider/rails/controller_authentication.rb +21 -0
  83. data/lib/oauth2/provider/random.rb +30 -0
  84. data/lib/oauth2/provider/version.rb +5 -0
  85. data/oauth2-provider.gemspec +35 -0
  86. data/spec/models/access_token_spec.rb +123 -0
  87. data/spec/models/authorization_code_spec.rb +115 -0
  88. data/spec/models/authorization_spec.rb +110 -0
  89. data/spec/models/client_spec.rb +75 -0
  90. data/spec/requests/access_tokens_controller_spec.rb +360 -0
  91. data/spec/requests/authentication_spec.rb +150 -0
  92. data/spec/requests/authorization_codes_support_spec.rb +157 -0
  93. data/spec/schema.rb +38 -0
  94. data/spec/set_backend_env_to_mongoid.rb +1 -0
  95. data/spec/spec_helper.rb +27 -0
  96. data/spec/support/activerecord_backend.rb +18 -0
  97. data/spec/support/factories.rb +56 -0
  98. data/spec/support/macros.rb +46 -0
  99. data/spec/support/mongoid_backend.rb +34 -0
  100. data/spec/support/rack.rb +32 -0
  101. metadata +373 -0
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ <p>We've been notified about this issue and we'll take a look at it shortly.</p>
24
+ </div>
25
+ </body>
26
+ </html>
File without changes
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-Agent: *
5
+ # Disallow: /
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,3 @@
1
+ require 'active_support/all'
2
+ require 'oauth2/provider/rails' if defined?(Rails)
3
+ require 'oauth2/provider'
@@ -0,0 +1,39 @@
1
+ module OAuth2
2
+ module Provider
3
+ autoload :Rails, 'oauth2/provider/rails'
4
+ autoload :Models, 'oauth2/provider/models'
5
+ autoload :Random, 'oauth2/provider/random'
6
+ autoload :Rack, 'oauth2/provider/rack'
7
+
8
+ mattr_accessor :backend
9
+ self.backend = :activerecord
10
+
11
+ mattr_accessor :authorization_class_name
12
+ mattr_accessor :access_token_class_name
13
+ mattr_accessor :authorization_code_class_name
14
+ mattr_accessor :client_class_name
15
+
16
+ [:resource_owner, :client, :authorization, :access_token, :authorization_code].each do |model|
17
+ instance_eval %{
18
+ def #{model}_class
19
+ #{model}_class_name.constantize
20
+ end
21
+ }
22
+ end
23
+
24
+ mattr_accessor :resource_owner_class_name
25
+ self.resource_owner_class_name = 'ResourceOwner'
26
+
27
+ def self.configure
28
+ yield self
29
+ activate
30
+ end
31
+
32
+ def self.activate
33
+ case backend
34
+ when :mongoid then OAuth2::Provider::Models::Mongoid.activate
35
+ else OAuth2::Provider::Models::ActiveRecord.activate
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,40 @@
1
+ module OAuth2::Provider::Models
2
+ autoload :ActiveRecord, 'oauth2/provider/models/active_record'
3
+ autoload :Mongoid, 'oauth2/provider/models/mongoid'
4
+
5
+ autoload :Authorization, 'oauth2/provider/models/authorization'
6
+ autoload :AccessToken, 'oauth2/provider/models/access_token'
7
+ autoload :AuthorizationCode, 'oauth2/provider/models/authorization_code'
8
+ autoload :Client, 'oauth2/provider/models/client'
9
+
10
+ module TokenExpiry
11
+ extend ActiveSupport::Concern
12
+
13
+ included do
14
+ mattr_accessor :default_token_lifespan
15
+ end
16
+
17
+ def initialize(*args, &block)
18
+ super
19
+ if default_token_lifespan
20
+ self.expires_at ||= default_token_lifespan.from_now
21
+ end
22
+ end
23
+
24
+ def fresh?
25
+ !expired?
26
+ end
27
+
28
+ def expired?
29
+ self.expires_at && self.expires_at < Time.now
30
+ end
31
+
32
+ def expires_in
33
+ if expired?
34
+ 0
35
+ else
36
+ self.expires_at.to_i - Time.now.to_i
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,54 @@
1
+ module OAuth2::Provider::Models::AccessToken
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ include OAuth2::Provider::Models::TokenExpiry
6
+ self.default_token_lifespan = 1.month
7
+
8
+ validates_presence_of :authorization, :access_token, :expires_at
9
+ validate :expires_at_isnt_greater_than_authorization
10
+
11
+ delegate :scope, :has_scope?, :client, :resource_owner, :to => :authorization
12
+ end
13
+
14
+ def initialize(*args, &block)
15
+ super
16
+ self.access_token ||= OAuth2::Provider::Random.base62(32)
17
+ self.refresh_token ||= OAuth2::Provider::Random.base62(32)
18
+ end
19
+
20
+ def as_json(options = {})
21
+ {"access_token" => access_token, "expires_in" => expires_in}.tap do |result|
22
+ result["refresh_token"] = refresh_token if refresh_token.present?
23
+ end
24
+ end
25
+
26
+ def refreshable?
27
+ refresh_token.present? && authorization.fresh?
28
+ end
29
+
30
+ private
31
+
32
+ def expires_at_isnt_greater_than_authorization
33
+ if !authorization.nil? && authorization.expires_at
34
+ unless expires_at.nil? || expires_at <= authorization.expires_at
35
+ errors.add(:expires_at, :must_be_less_than_authorization)
36
+ end
37
+ end
38
+ end
39
+
40
+ module ClassMethods
41
+ def refresh_with(refresh_token)
42
+ if refresh_token && token = find_by_refresh_token(refresh_token)
43
+ if token.refreshable?
44
+ new(:authorization => token.authorization).tap do |result|
45
+ if result.authorization.expires_at && result.authorization.expires_at < result.expires_at
46
+ result.expires_at = result.authorization.expires_at
47
+ end
48
+ result.save!
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,30 @@
1
+ module OAuth2::Provider::Models::ActiveRecord
2
+ autoload :Authorization, 'oauth2/provider/models/active_record/authorization'
3
+ autoload :AccessToken, 'oauth2/provider/models/active_record/access_token'
4
+ autoload :AuthorizationCode, 'oauth2/provider/models/active_record/authorization_code'
5
+ autoload :Client, 'oauth2/provider/models/active_record/client'
6
+
7
+ mattr_accessor :client_table_name
8
+ self.client_table_name = 'oauth_clients'
9
+
10
+ mattr_accessor :access_token_table_name
11
+ self.access_token_table_name = 'oauth_access_tokens'
12
+
13
+ mattr_accessor :authorization_code_table_name
14
+ self.authorization_code_table_name = 'oauth_authorization_codes'
15
+
16
+ mattr_accessor :authorization_table_name
17
+ self.authorization_table_name = 'oauth_authorizations'
18
+
19
+ def self.activate(options = {})
20
+ OAuth2::Provider.client_class_name ||= "OAuth2::Provider::Models::ActiveRecord::Client"
21
+ OAuth2::Provider.access_token_class_name ||= "OAuth2::Provider::Models::ActiveRecord::AccessToken"
22
+ OAuth2::Provider.authorization_code_class_name ||= "OAuth2::Provider::Models::ActiveRecord::AuthorizationCode"
23
+ OAuth2::Provider.authorization_class_name ||= "OAuth2::Provider::Models::ActiveRecord::Authorization"
24
+
25
+ OAuth2::Provider.client_class.set_table_name client_table_name
26
+ OAuth2::Provider.access_token_class.set_table_name access_token_table_name
27
+ OAuth2::Provider.authorization_code_class.set_table_name authorization_code_table_name
28
+ OAuth2::Provider.authorization_class.set_table_name authorization_table_name
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ class OAuth2::Provider::Models::ActiveRecord::AccessToken < ActiveRecord::Base
2
+ module Behaviour
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include OAuth2::Provider::Models::AccessToken
7
+
8
+ belongs_to :authorization, :class_name => OAuth2::Provider.authorization_class_name, :foreign_key => 'authorization_id'
9
+ end
10
+ end
11
+
12
+ include Behaviour
13
+ end
@@ -0,0 +1,16 @@
1
+ class OAuth2::Provider::Models::ActiveRecord::Authorization < ActiveRecord::Base
2
+ module Behaviour
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include OAuth2::Provider::Models::Authorization
7
+
8
+ belongs_to :client, :class_name => OAuth2::Provider.client_class_name, :foreign_key => 'client_id'
9
+
10
+ has_many :access_tokens, :class_name => OAuth2::Provider.access_token_class_name, :foreign_key => 'authorization_id'
11
+ has_many :authorization_codes, :class_name => OAuth2::Provider.authorization_code_class_name, :foreign_key => 'authorization_id'
12
+ end
13
+ end
14
+
15
+ include Behaviour
16
+ end
@@ -0,0 +1,13 @@
1
+ class OAuth2::Provider::Models::ActiveRecord::AuthorizationCode < ActiveRecord::Base
2
+ module Behaviour
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include OAuth2::Provider::Models::AuthorizationCode
7
+
8
+ belongs_to :authorization, :class_name => OAuth2::Provider.authorization_class_name, :foreign_key => 'authorization_id'
9
+ end
10
+ end
11
+
12
+ include Behaviour
13
+ end
@@ -0,0 +1,15 @@
1
+ class OAuth2::Provider::Models::ActiveRecord::Client < ActiveRecord::Base
2
+ module Behaviour
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include OAuth2::Provider::Models::Client
7
+
8
+ has_many :authorizations, :class_name => OAuth2::Provider.authorization_class_name, :foreign_key => 'client_id'
9
+ has_many :authorization_codes, :through => :authorizations, :class_name => OAuth2::Provider.authorization_code_class_name
10
+ has_many :access_tokens, :through => :authorizations, :class_name => OAuth2::Provider.access_token_class_name
11
+ end
12
+ end
13
+
14
+ include Behaviour
15
+ end
@@ -0,0 +1,40 @@
1
+ module OAuth2::Provider::Models::Authorization
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ include OAuth2::Provider::Models::TokenExpiry
6
+ self.default_token_lifespan = nil
7
+
8
+ validates_presence_of :client
9
+ end
10
+
11
+ def has_scope?(s)
12
+ scope && scope.split(" ").include?(s)
13
+ end
14
+
15
+ def revoke
16
+ authorization_codes.destroy_all
17
+ access_tokens.destroy_all
18
+ destroy
19
+ end
20
+
21
+ def resource_owner=(ro)
22
+ self.resource_owner_id = ro && ro.id
23
+ self.resource_owner_type = ro && ro.class.name
24
+ end
25
+
26
+ def resource_owner
27
+ resource_owner_id && resource_owner_class.find(resource_owner_id)
28
+ end
29
+
30
+ def resource_owner_class
31
+ resource_owner_type.constantize
32
+ end
33
+
34
+ module ClassMethods
35
+ def all_for(ro)
36
+ return [] unless ro
37
+ self.where(:resource_owner_id => ro.id, :resource_owner_type => ro.class.name).all
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ module OAuth2::Provider::Models::AuthorizationCode
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ include OAuth2::Provider::Models::TokenExpiry
6
+ self.default_token_lifespan = 1.minute
7
+
8
+ delegate :client, :resource_owner, :to => :authorization
9
+ validates_presence_of :authorization, :code, :expires_at, :redirect_uri
10
+ end
11
+
12
+ def initialize(attributes = {})
13
+ super
14
+ self.code ||= OAuth2::Provider::Random.base62(32)
15
+ end
16
+
17
+ module ClassMethods
18
+ def claim(code, redirect_uri)
19
+ if authorization_code = find_by_code_and_redirect_uri(code, redirect_uri)
20
+ if authorization_code.fresh?
21
+ authorization_code.destroy
22
+ authorization_code.authorization.access_tokens.create!
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ module OAuth2::Provider::Models::Client
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ validates_presence_of :oauth_identifier, :oauth_secret, :name
6
+ validates_uniqueness_of :oauth_identifier
7
+ end
8
+
9
+ def initialize(*args, &block)
10
+ super
11
+ self.oauth_identifier ||= OAuth2::Provider::Random.base62(16)
12
+ self.oauth_secret ||= OAuth2::Provider::Random.base62(32)
13
+ end
14
+
15
+ def to_param
16
+ new_record? ? nil : oauth_identifier
17
+ end
18
+
19
+ def allow_grant_type?(grant_type)
20
+ true
21
+ end
22
+
23
+ module ClassMethods
24
+ def from_param(identifier)
25
+ self.find_by_oauth_identifier(identifier)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ module OAuth2::Provider::Models::Mongoid
2
+ autoload :Authorization, 'oauth2/provider/models/mongoid/authorization'
3
+ autoload :AccessToken, 'oauth2/provider/models/mongoid/access_token'
4
+ autoload :AuthorizationCode, 'oauth2/provider/models/mongoid/authorization_code'
5
+ autoload :Client, 'oauth2/provider/models/mongoid/client'
6
+
7
+ mattr_accessor :client_collection_name
8
+ self.client_collection_name = 'oauth_clients'
9
+
10
+ mattr_accessor :access_token_collection_name
11
+ self.access_token_collection_name = 'oauth_access_tokens'
12
+
13
+ mattr_accessor :authorization_code_collection_name
14
+ self.authorization_code_collection_name = 'oauth_authorization_codes'
15
+
16
+ mattr_accessor :authorization_collection_name
17
+ self.authorization_collection_name = 'oauth_authorizations'
18
+
19
+ def self.activate(options = {})
20
+ OAuth2::Provider.client_class_name ||= "OAuth2::Provider::Models::Mongoid::Client"
21
+ OAuth2::Provider.access_token_class_name ||= "OAuth2::Provider::Models::Mongoid::AccessToken"
22
+ OAuth2::Provider.authorization_code_class_name ||= "OAuth2::Provider::Models::Mongoid::AuthorizationCode"
23
+ OAuth2::Provider.authorization_class_name ||= "OAuth2::Provider::Models::Mongoid::Authorization"
24
+
25
+ OAuth2::Provider.client_class.collection_name = client_collection_name
26
+ OAuth2::Provider.access_token_class.collection_name = access_token_collection_name
27
+ OAuth2::Provider.authorization_code_class.collection_name = authorization_code_collection_name
28
+ OAuth2::Provider.authorization_class.collection_name = authorization_collection_name
29
+ end
30
+ end