grape_oauth2 0.1.1

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 (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +18 -0
  5. data/.travis.yml +42 -0
  6. data/Gemfile +23 -0
  7. data/README.md +820 -0
  8. data/Rakefile +11 -0
  9. data/gemfiles/active_record.rb +25 -0
  10. data/gemfiles/mongoid.rb +14 -0
  11. data/gemfiles/sequel.rb +24 -0
  12. data/grape_oauth2.gemspec +27 -0
  13. data/grape_oauth2.png +0 -0
  14. data/lib/grape_oauth2.rb +129 -0
  15. data/lib/grape_oauth2/configuration.rb +143 -0
  16. data/lib/grape_oauth2/configuration/class_accessors.rb +36 -0
  17. data/lib/grape_oauth2/configuration/validation.rb +71 -0
  18. data/lib/grape_oauth2/endpoints/authorize.rb +34 -0
  19. data/lib/grape_oauth2/endpoints/token.rb +72 -0
  20. data/lib/grape_oauth2/gem_version.rb +24 -0
  21. data/lib/grape_oauth2/generators/authorization.rb +44 -0
  22. data/lib/grape_oauth2/generators/base.rb +26 -0
  23. data/lib/grape_oauth2/generators/token.rb +62 -0
  24. data/lib/grape_oauth2/helpers/access_token_helpers.rb +54 -0
  25. data/lib/grape_oauth2/helpers/oauth_params.rb +41 -0
  26. data/lib/grape_oauth2/mixins/active_record/access_grant.rb +47 -0
  27. data/lib/grape_oauth2/mixins/active_record/access_token.rb +75 -0
  28. data/lib/grape_oauth2/mixins/active_record/client.rb +35 -0
  29. data/lib/grape_oauth2/mixins/mongoid/access_grant.rb +58 -0
  30. data/lib/grape_oauth2/mixins/mongoid/access_token.rb +88 -0
  31. data/lib/grape_oauth2/mixins/mongoid/client.rb +41 -0
  32. data/lib/grape_oauth2/mixins/sequel/access_grant.rb +68 -0
  33. data/lib/grape_oauth2/mixins/sequel/access_token.rb +86 -0
  34. data/lib/grape_oauth2/mixins/sequel/client.rb +46 -0
  35. data/lib/grape_oauth2/responses/authorization.rb +10 -0
  36. data/lib/grape_oauth2/responses/base.rb +56 -0
  37. data/lib/grape_oauth2/responses/token.rb +10 -0
  38. data/lib/grape_oauth2/scopes.rb +74 -0
  39. data/lib/grape_oauth2/strategies/authorization_code.rb +38 -0
  40. data/lib/grape_oauth2/strategies/base.rb +47 -0
  41. data/lib/grape_oauth2/strategies/client_credentials.rb +20 -0
  42. data/lib/grape_oauth2/strategies/password.rb +22 -0
  43. data/lib/grape_oauth2/strategies/refresh_token.rb +47 -0
  44. data/lib/grape_oauth2/unique_token.rb +20 -0
  45. data/lib/grape_oauth2/version.rb +14 -0
  46. data/spec/configuration/config_spec.rb +231 -0
  47. data/spec/configuration/version_spec.rb +12 -0
  48. data/spec/dummy/endpoints/custom_authorization.rb +25 -0
  49. data/spec/dummy/endpoints/custom_token.rb +35 -0
  50. data/spec/dummy/endpoints/status.rb +25 -0
  51. data/spec/dummy/grape_oauth2_config.rb +11 -0
  52. data/spec/dummy/orm/active_record/app/config/db.rb +7 -0
  53. data/spec/dummy/orm/active_record/app/models/access_code.rb +3 -0
  54. data/spec/dummy/orm/active_record/app/models/access_token.rb +3 -0
  55. data/spec/dummy/orm/active_record/app/models/application.rb +3 -0
  56. data/spec/dummy/orm/active_record/app/models/application_record.rb +3 -0
  57. data/spec/dummy/orm/active_record/app/models/user.rb +10 -0
  58. data/spec/dummy/orm/active_record/app/twitter.rb +36 -0
  59. data/spec/dummy/orm/active_record/config.ru +7 -0
  60. data/spec/dummy/orm/active_record/db/schema.rb +53 -0
  61. data/spec/dummy/orm/mongoid/app/config/db.rb +6 -0
  62. data/spec/dummy/orm/mongoid/app/config/mongoid.yml +21 -0
  63. data/spec/dummy/orm/mongoid/app/models/access_code.rb +3 -0
  64. data/spec/dummy/orm/mongoid/app/models/access_token.rb +3 -0
  65. data/spec/dummy/orm/mongoid/app/models/application.rb +3 -0
  66. data/spec/dummy/orm/mongoid/app/models/user.rb +11 -0
  67. data/spec/dummy/orm/mongoid/app/twitter.rb +34 -0
  68. data/spec/dummy/orm/mongoid/config.ru +5 -0
  69. data/spec/dummy/orm/sequel/app/config/db.rb +1 -0
  70. data/spec/dummy/orm/sequel/app/models/access_code.rb +4 -0
  71. data/spec/dummy/orm/sequel/app/models/access_token.rb +4 -0
  72. data/spec/dummy/orm/sequel/app/models/application.rb +4 -0
  73. data/spec/dummy/orm/sequel/app/models/application_record.rb +2 -0
  74. data/spec/dummy/orm/sequel/app/models/user.rb +11 -0
  75. data/spec/dummy/orm/sequel/app/twitter.rb +47 -0
  76. data/spec/dummy/orm/sequel/config.ru +5 -0
  77. data/spec/dummy/orm/sequel/db/schema.rb +50 -0
  78. data/spec/lib/scopes_spec.rb +50 -0
  79. data/spec/mixins/active_record/access_token_spec.rb +185 -0
  80. data/spec/mixins/active_record/client_spec.rb +95 -0
  81. data/spec/mixins/mongoid/access_token_spec.rb +185 -0
  82. data/spec/mixins/mongoid/client_spec.rb +95 -0
  83. data/spec/mixins/sequel/access_token_spec.rb +185 -0
  84. data/spec/mixins/sequel/client_spec.rb +96 -0
  85. data/spec/requests/flows/authorization_code_spec.rb +67 -0
  86. data/spec/requests/flows/client_credentials_spec.rb +101 -0
  87. data/spec/requests/flows/password_spec.rb +210 -0
  88. data/spec/requests/flows/refresh_token_spec.rb +222 -0
  89. data/spec/requests/flows/revoke_token_spec.rb +103 -0
  90. data/spec/requests/protected_resources_spec.rb +64 -0
  91. data/spec/spec_helper.rb +60 -0
  92. data/spec/support/api_helper.rb +11 -0
  93. metadata +257 -0
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Grape::OAuth2 Version' do
4
+ it 'has a version string' do
5
+ expect(Grape::OAuth2::VERSION::STRING).to be_present
6
+ end
7
+
8
+ it 'returns version as an instance of Gem::Version' do
9
+ expect(Grape::OAuth2.gem_version).to be_an_instance_of(Gem::Version)
10
+ expect(Grape::OAuth2.version).to be_an_instance_of(Gem::Version)
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ module Twitter
2
+ module Endpoints
3
+ class CustomAuthorization < ::Grape::API
4
+ helpers Grape::OAuth2::Helpers::OAuthParams
5
+
6
+ namespace :oauth do
7
+ params do
8
+ use :oauth_authorization_params
9
+ end
10
+
11
+ post :custom_authorize do
12
+ response = Grape::OAuth2::Generators::Authorization.generate_for(env) do |request, response|
13
+ request.unsupported_response_type!
14
+ end
15
+
16
+ # Status
17
+ status response.status
18
+
19
+ # Body
20
+ body response.body
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ module Twitter
2
+ module Endpoints
3
+ class CustomToken < ::Grape::API
4
+ helpers Grape::OAuth2::Helpers::OAuthParams
5
+
6
+ namespace :oauth do
7
+ params do
8
+ use :oauth_token_params
9
+ end
10
+
11
+ post :custom_token do
12
+ token_response = Grape::OAuth2::Generators::Token.generate_for(env) do |request, response|
13
+ # Custom client authentication:
14
+ client = Grape::OAuth2::Strategies::Base.authenticate_client(request)
15
+ request.invalid_client! if client.nil? || client.name != 'Admin'
16
+
17
+ resource_owner = Grape::OAuth2::Strategies::Base.authenticate_resource_owner(client, request)
18
+ request.invalid_grant! if resource_owner.nil?
19
+
20
+ token = AccessToken.create_for(client, resource_owner, request.scope.join(' '))
21
+ response.access_token = Grape::OAuth2::Strategies::Base.expose_to_bearer_token(token)
22
+ end
23
+
24
+ status token_response.status
25
+
26
+ token_response.headers.each do |key, value|
27
+ header key, value
28
+ end
29
+
30
+ body token_response.body
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ module Twitter
2
+ module Endpoints
3
+ class Status < Grape::API
4
+ before do
5
+ access_token_required!
6
+ end
7
+
8
+ resources :status do
9
+ get do
10
+ { value: 'Nice day!', current_user: current_resource_owner.username }
11
+ end
12
+
13
+ get :single_scope, scopes: [:read] do
14
+ { value: 'Access granted' }
15
+ end
16
+
17
+ get :multiple_scopes, scopes: [:read, :write] do
18
+ access_token_required!
19
+
20
+ { value: 'Access granted' }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ # Common config across all the ORMs
2
+ Grape::OAuth2.configure do |config|
3
+ config.client_class_name = 'Application'
4
+ config.access_token_class_name = 'AccessToken'
5
+ config.resource_owner_class_name = 'User'
6
+ config.access_grant_class_name = 'AccessCode'
7
+
8
+ config.realm = 'Custom Realm'
9
+
10
+ config.allowed_grant_types << 'refresh_token'
11
+ end
@@ -0,0 +1,7 @@
1
+ OTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: ':memory:')
2
+
3
+ ::ActiveRecord::Base.default_timezone = :utc
4
+ ::ActiveRecord::Base.logger = ENV['RAILS_ENV'] == 'test' ? nil : Logger.new(STDOUT)
5
+
6
+ ::ActiveRecord::Migration.verbose = false
7
+ load File.expand_path('../../../db/schema.rb', __FILE__)
@@ -0,0 +1,3 @@
1
+ class AccessCode < ApplicationRecord
2
+ include Grape::OAuth2::ActiveRecord::AccessGrant
3
+ end
@@ -0,0 +1,3 @@
1
+ class AccessToken < ApplicationRecord
2
+ include Grape::OAuth2::ActiveRecord::AccessToken
3
+ end
@@ -0,0 +1,3 @@
1
+ class Application < ApplicationRecord
2
+ include Grape::OAuth2::ActiveRecord::Client
3
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationRecord < ::ActiveRecord::Base
2
+ self.abstract_class = true
3
+ end
@@ -0,0 +1,10 @@
1
+ class User < ApplicationRecord
2
+ has_secure_password
3
+
4
+ def self.oauth_authenticate(_client, username, password)
5
+ user = find_by(username: username)
6
+ return if user.nil?
7
+
8
+ user.authenticate(password)
9
+ end
10
+ end
@@ -0,0 +1,36 @@
1
+ require 'otr-activerecord'
2
+ require 'grape'
3
+
4
+ require File.expand_path('../../../../../../lib/grape_oauth2', __FILE__)
5
+
6
+ # Database
7
+ load File.expand_path('../config/db.rb', __FILE__)
8
+
9
+ # Grape::OAuth2 config
10
+ load File.expand_path('../../../../grape_oauth2_config.rb', __FILE__)
11
+
12
+ # Models
13
+ require_relative 'models/application_record'
14
+ require_relative 'models/access_token'
15
+ require_relative 'models/access_code'
16
+ require_relative 'models/application'
17
+ require_relative 'models/user'
18
+
19
+ # Twitter Endpoints
20
+ require_relative '../../../endpoints/custom_token'
21
+ require_relative '../../../endpoints/custom_authorization'
22
+ require_relative '../../../endpoints/status'
23
+
24
+ module Twitter
25
+ class API < Grape::API
26
+ version 'v1', using: :path
27
+ format :json
28
+ prefix :api
29
+
30
+ include Grape::OAuth2.api
31
+
32
+ mount Twitter::Endpoints::Status
33
+ mount Twitter::Endpoints::CustomToken
34
+ mount Twitter::Endpoints::CustomAuthorization
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ require 'app/twitter'
4
+
5
+ use OTR::ActiveRecord::ConnectionManagement
6
+
7
+ run Twitter::API
@@ -0,0 +1,53 @@
1
+ ActiveRecord::Schema.define(version: 3) do
2
+ create_table :users do |t|
3
+ t.string :name
4
+ t.string :username
5
+ t.string :password_digest
6
+ end
7
+
8
+ create_table :applications do |t|
9
+ t.string :name
10
+ t.string :key
11
+ t.string :secret
12
+ t.string :redirect_uri
13
+
14
+ t.timestamps null: false
15
+ end
16
+
17
+ add_index :applications, :key, unique: true
18
+
19
+ create_table :access_tokens do |t|
20
+ t.integer :resource_owner_id
21
+ t.integer :client_id
22
+
23
+ t.string :token, null: false
24
+ t.string :refresh_token
25
+ t.string :scopes
26
+
27
+ t.datetime :expires_at
28
+ t.datetime :revoked_at
29
+ t.datetime :created_at, null: false
30
+ end
31
+
32
+ create_table :access_codes do |t|
33
+ t.integer :resource_owner_id
34
+ t.integer :client_id
35
+
36
+ t.string :token, null: false
37
+ t.string :redirect_uri
38
+ t.string :scopes
39
+
40
+ t.datetime :expires_at
41
+ t.datetime :revoked_at
42
+ t.datetime :created_at, null: false
43
+ end
44
+
45
+ add_index :access_tokens, :token, unique: true
46
+ add_index :access_tokens, :resource_owner_id
47
+ add_index :access_tokens, :client_id
48
+ add_index :access_tokens, :refresh_token, unique: true
49
+
50
+ add_index :access_codes, :token, unique: true
51
+ add_index :access_codes, :resource_owner_id
52
+ add_index :access_codes, :client_id
53
+ end
@@ -0,0 +1,6 @@
1
+ Mongoid.load!(File.expand_path('../mongoid.yml', __FILE__), :test)
2
+
3
+ Mongoid.raise_not_found_error = false
4
+
5
+ Mongoid.logger.level = Logger::ERROR
6
+ Mongo::Logger.logger.level = Logger::ERROR
@@ -0,0 +1,21 @@
1
+ development:
2
+ clients:
3
+ default:
4
+ database: mongoid-dev
5
+ hosts:
6
+ - localhost:27017
7
+ options:
8
+ raise_not_found_error: false
9
+ write:
10
+ w: 1
11
+
12
+ test:
13
+ clients:
14
+ default:
15
+ database: mongoid-test
16
+ hosts:
17
+ - localhost:27017
18
+ options:
19
+ raise_not_found_error: false
20
+ write:
21
+ w: 1
@@ -0,0 +1,3 @@
1
+ class AccessCode
2
+ include Grape::OAuth2::Mongoid::AccessGrant
3
+ end
@@ -0,0 +1,3 @@
1
+ class AccessToken
2
+ include Grape::OAuth2::Mongoid::AccessToken
3
+ end
@@ -0,0 +1,3 @@
1
+ class Application
2
+ include Grape::OAuth2::Mongoid::Client
3
+ end
@@ -0,0 +1,11 @@
1
+ class User
2
+ include Mongoid::Document
3
+ include Mongoid::Timestamps
4
+
5
+ field :username, type: String
6
+ field :password, type: String
7
+
8
+ def self.oauth_authenticate(_client, username, password)
9
+ find_by(username: username, password: password)
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ require 'grape'
2
+
3
+ require File.expand_path('../../../../../../lib/grape_oauth2', __FILE__)
4
+
5
+ # Database
6
+ load File.expand_path('../config/db.rb', __FILE__)
7
+
8
+ # Grape::OAuth2 config
9
+ load File.expand_path('../../../../grape_oauth2_config.rb', __FILE__)
10
+
11
+ # Models
12
+ require_relative 'models/access_token'
13
+ require_relative 'models/access_code'
14
+ require_relative 'models/application'
15
+ require_relative 'models/user'
16
+
17
+ # Twitter Endpoints
18
+ require_relative '../../../endpoints/custom_token'
19
+ require_relative '../../../endpoints/custom_authorization'
20
+ require_relative '../../../endpoints/status'
21
+
22
+ module Twitter
23
+ class API < Grape::API
24
+ version 'v1', using: :path
25
+ format :json
26
+ prefix :api
27
+
28
+ include Grape::OAuth2.api
29
+
30
+ mount Twitter::Endpoints::Status
31
+ mount Twitter::Endpoints::CustomToken
32
+ mount Twitter::Endpoints::CustomAuthorization
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ require 'app/twitter'
4
+
5
+ run Twitter::API
@@ -0,0 +1 @@
1
+ load File.expand_path('../../../db/schema.rb', __FILE__)
@@ -0,0 +1,4 @@
1
+ class AccessCode < ApplicationRecord
2
+ set_dataset :access_codes
3
+ include Grape::OAuth2::Sequel::AccessGrant
4
+ end
@@ -0,0 +1,4 @@
1
+ class AccessToken < ApplicationRecord
2
+ set_dataset :access_tokens
3
+ include Grape::OAuth2::Sequel::AccessToken
4
+ end
@@ -0,0 +1,4 @@
1
+ class Application < ApplicationRecord
2
+ set_dataset :applications
3
+ include Grape::OAuth2::Sequel::Client
4
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationRecord < ::Sequel::Model
2
+ end
@@ -0,0 +1,11 @@
1
+ class User < ApplicationRecord
2
+ set_dataset :users
3
+ plugin :secure_password, include_validations: false
4
+
5
+ def self.oauth_authenticate(_client, username, password)
6
+ user = find(username: username)
7
+ return if user.nil?
8
+
9
+ user.authenticate(password)
10
+ end
11
+ end
@@ -0,0 +1,47 @@
1
+ require 'grape'
2
+
3
+ require File.expand_path('../../../../../../lib/grape_oauth2', __FILE__)
4
+
5
+ # SQLite memory database
6
+ DB = if defined?(JRUBY_VERSION)
7
+ Sequel.connect('jdbc:sqlite::memory:')
8
+ else
9
+ Sequel.sqlite
10
+ end
11
+
12
+ # Database
13
+ load File.expand_path('../config/db.rb', __FILE__)
14
+
15
+ # Grape::OAuth2 config
16
+ load File.expand_path('../../../../grape_oauth2_config.rb', __FILE__)
17
+
18
+ # Models
19
+ require_relative 'models/application_record'
20
+ require_relative 'models/access_token'
21
+ require_relative 'models/access_code'
22
+ require_relative 'models/application'
23
+ require_relative 'models/user'
24
+
25
+ # Twitter Endpoints
26
+ require_relative '../../../endpoints/custom_token'
27
+ require_relative '../../../endpoints/custom_authorization'
28
+ require_relative '../../../endpoints/status'
29
+
30
+ module Twitter
31
+ class API < Grape::API
32
+ version 'v1', using: :path
33
+ format :json
34
+ prefix :api
35
+
36
+ use *Grape::OAuth2.middleware
37
+
38
+ helpers Grape::OAuth2::Helpers::AccessTokenHelpers
39
+
40
+ mount Grape::OAuth2::Endpoints::Token
41
+ mount Grape::OAuth2::Endpoints::Authorize
42
+
43
+ mount Twitter::Endpoints::Status
44
+ mount Twitter::Endpoints::CustomToken
45
+ mount Twitter::Endpoints::CustomAuthorization
46
+ end
47
+ end