simple_oauth2 0.0.0

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +25 -0
  3. data/.coveralls.yml +1 -0
  4. data/.gitignore +26 -0
  5. data/.hound.yml +4 -0
  6. data/.rubocop.yml +5 -0
  7. data/.rubocop_todo.yml +12 -0
  8. data/.travis.yml +31 -0
  9. data/Gemfile +18 -0
  10. data/LICENSE +21 -0
  11. data/README.md +11 -0
  12. data/Rakefile +11 -0
  13. data/gemfiles/nobrainer.rb +15 -0
  14. data/lib/simple_oauth2/configuration/class_accessors.rb +36 -0
  15. data/lib/simple_oauth2/configuration/constants.rb +36 -0
  16. data/lib/simple_oauth2/configuration.rb +169 -0
  17. data/lib/simple_oauth2/generators/authorization.rb +64 -0
  18. data/lib/simple_oauth2/generators/base.rb +31 -0
  19. data/lib/simple_oauth2/generators/token.rb +71 -0
  20. data/lib/simple_oauth2/helpers.rb +40 -0
  21. data/lib/simple_oauth2/mixins/nobrainer/access_grant.rb +62 -0
  22. data/lib/simple_oauth2/mixins/nobrainer/access_token.rb +98 -0
  23. data/lib/simple_oauth2/mixins/nobrainer/client.rb +43 -0
  24. data/lib/simple_oauth2/resource/bearer.rb +20 -0
  25. data/lib/simple_oauth2/responses.rb +62 -0
  26. data/lib/simple_oauth2/scopes.rb +59 -0
  27. data/lib/simple_oauth2/strategies/authorization_code.rb +22 -0
  28. data/lib/simple_oauth2/strategies/base.rb +61 -0
  29. data/lib/simple_oauth2/strategies/client_credentials.rb +21 -0
  30. data/lib/simple_oauth2/strategies/code.rb +25 -0
  31. data/lib/simple_oauth2/strategies/password.rb +21 -0
  32. data/lib/simple_oauth2/strategies/refresh_token.rb +53 -0
  33. data/lib/simple_oauth2/strategies/token.rb +24 -0
  34. data/lib/simple_oauth2/uniq_token.rb +20 -0
  35. data/lib/simple_oauth2/version.rb +26 -0
  36. data/lib/simple_oauth2.rb +62 -0
  37. data/logo.png +0 -0
  38. data/simple_oauth2.gemspec +22 -0
  39. data/spec/configuration/config_spec.rb +181 -0
  40. data/spec/configuration/version_spec.rb +11 -0
  41. data/spec/dummy/endpoints/authorization.rb +15 -0
  42. data/spec/dummy/endpoints/custom_authorization.rb +21 -0
  43. data/spec/dummy/endpoints/custom_token.rb +21 -0
  44. data/spec/dummy/endpoints/status.rb +51 -0
  45. data/spec/dummy/endpoints/token.rb +22 -0
  46. data/spec/dummy/orm/nobrainer/app/config/db.rb +8 -0
  47. data/spec/dummy/orm/nobrainer/app/models/access_grant.rb +3 -0
  48. data/spec/dummy/orm/nobrainer/app/models/access_token.rb +3 -0
  49. data/spec/dummy/orm/nobrainer/app/models/client.rb +3 -0
  50. data/spec/dummy/orm/nobrainer/app/models/user.rb +11 -0
  51. data/spec/dummy/orm/nobrainer/app/twitter.rb +51 -0
  52. data/spec/dummy/orm/nobrainer/config.ru +37 -0
  53. data/spec/dummy/simple_oauth2_config.rb +7 -0
  54. data/spec/requests/flows/authorization_code_spec.rb +177 -0
  55. data/spec/requests/flows/client_credentials_spec.rb +163 -0
  56. data/spec/requests/flows/code_spec.rb +98 -0
  57. data/spec/requests/flows/password_spec.rb +183 -0
  58. data/spec/requests/flows/refresh_token_spec.rb +282 -0
  59. data/spec/requests/flows/token_spec.rb +113 -0
  60. data/spec/requests/protected_resources_spec.rb +65 -0
  61. data/spec/requests/revoke_token_spec.rb +90 -0
  62. data/spec/spec_helper.rb +51 -0
  63. data/spec/support/helper.rb +11 -0
  64. metadata +125 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7457463729d7d0b17d67f13e8f0865f8340d8e59
4
+ data.tar.gz: 85c2c6a42f9085f0636c4fca5e72339b542c7a48
5
+ SHA512:
6
+ metadata.gz: 5e0ff90478bd45cd417ef769086b492252375fcefdea551d7f853df51096c3513be1b399322f70ade0392a7a3c9cd9acc3ff05a969b9fc647acc15d859a47b0c
7
+ data.tar.gz: 4575200800986eac07b0bae126b44a144cbd5ebc5ff7a2cecec0da2eedba32b055e1f62445c90b3b79bd7fe16c76ad24df83190924ef9a04b86587ef45c09b14
data/.codeclimate.yml ADDED
@@ -0,0 +1,25 @@
1
+ ---
2
+ engines:
3
+ duplication:
4
+ enabled: true
5
+ config:
6
+ languages:
7
+ - ruby
8
+ - javascript
9
+ - python
10
+ - php
11
+ fixme:
12
+ enabled: true
13
+ rubocop:
14
+ enabled: true
15
+ ratings:
16
+ paths:
17
+ - "**.inc"
18
+ - "**.js"
19
+ - "**.jsx"
20
+ - "**.module"
21
+ - "**.php"
22
+ - "**.py"
23
+ - "**.rb"
24
+ exclude_paths:
25
+ - spec/
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore ADDED
@@ -0,0 +1,26 @@
1
+ *.gem
2
+ *.rbc
3
+ .rbx
4
+ /coverage/
5
+ Gemfile.lock
6
+ gemfiles/*.lock
7
+
8
+ ## Documentation cache and generated files:
9
+ /.yardoc/
10
+ /_yardoc/
11
+ /doc/
12
+ /rdoc/
13
+
14
+ ## Environment normalization:
15
+ .bundle/
16
+
17
+ rethinkdb_data
18
+
19
+ # for a library or gem, you might want to ignore these files since the code is
20
+ # intended to run in multiple environments; otherwise, check them in:
21
+ # Gemfile.lock
22
+ # .ruby-version
23
+ # .ruby-gemset
24
+
25
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
26
+ .rvmrc
data/.hound.yml ADDED
@@ -0,0 +1,4 @@
1
+ ruby:
2
+ config_file: .rubocop_todo.yml
3
+
4
+ fail_on_violations: true
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ AllCops:
2
+ Exclude:
3
+ - rethinkdb_data
4
+
5
+ inherit_from: .rubocop_todo.yml
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,12 @@
1
+ Style/FrozenStringLiteralComment:
2
+ Enabled: false
3
+ Style/StringLiterals:
4
+ EnforcedStyle: single_quotes
5
+ Metrics/MethodLength:
6
+ Max: 15
7
+ Metrics/LineLength:
8
+ Max: 120
9
+ Style/Lambda:
10
+ Enabled: false
11
+ Style/DotPosition:
12
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,31 @@
1
+ language: ruby
2
+ cache: bundler
3
+ bundler_args: --without yard guard benchmarks
4
+ notifications:
5
+ email: false
6
+ addons:
7
+ code_climate:
8
+ repo_token: b06efdea32dd6768ddb83b21e07f85d439a6c725eaa97c8981324a14cbcbee17
9
+
10
+ before_install:
11
+ - source /etc/lsb-release && echo "deb http://download.rethinkdb.com/apt $DISTRIB_CODENAME main" | sudo tee /etc/apt/sources.list.d/rethinkdb.list
12
+ - wget -qO- http://download.rethinkdb.com/apt/pubkey.gpg | sudo apt-key add -
13
+ - sudo apt-get update -q
14
+ - sudo apt-get install rethinkdb
15
+ - sudo cp /etc/rethinkdb/default.conf.sample /etc/rethinkdb/instances.d/instance1.conf
16
+ - sudo service rethinkdb restart
17
+ - gem install bundler -v '~> 1.10'
18
+
19
+ matrix:
20
+ allow_failures:
21
+ - rvm: ruby-head
22
+ include:
23
+ - rvm: 2.2.6
24
+ gemfile: gemfiles/nobrainer.rb
25
+ env: ORM=nobrainer
26
+ - rvm: 2.3.3
27
+ gemfile: gemfiles/nobrainer.rb
28
+ env: ORM=nobrainer
29
+ - rvm: ruby-head
30
+ gemfile: gemfiles/nobrainer.rb
31
+ env: ORM=nobrainer
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rack-oauth2'
6
+
7
+ group :test do
8
+ gem 'nobrainer'
9
+
10
+ gem 'coveralls', require: false
11
+ gem 'ffaker'
12
+ gem 'rack-test', require: 'rack/test'
13
+ gem 'rspec-rails', '~> 3.4'
14
+ gem 'rubocop', '~> 0.46.0', require: false
15
+ gem 'simplecov', require: false
16
+ end
17
+
18
+ gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Volodimir Partytskyi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ ![Simple OAuth2 Logo](https://raw.github.com/simple-oauth2/simple_oauth2/master/logo.png)
2
+
3
+ [![Build Status](https://travis-ci.org/simple-oauth2/simple_oauth2.svg?branch=master)](https://travis-ci.org/simple-oauth2/simple_oauth2)
4
+ [![Dependency Status](https://gemnasium.com/badges/github.com/simple-oauth2/simple_oauth2.svg)](https://gemnasium.com/github.com/simple-oauth2/simple_oauth2)
5
+ [![Coverage Status](https://coveralls.io/repos/github/simple-oauth2/simple_oauth2/badge.svg?branch=master)](https://coveralls.io/github/simple-oauth2/simple_oauth2?branch=master)
6
+ [![Code Climate](https://codeclimate.com/github/simple-oauth2/simple_oauth2/badges/gpa.svg)](https://codeclimate.com/github/simple-oauth2/simple_oauth2)
7
+ [![Inline docs](http://inch-ci.org/github/simple-oauth2/simple_oauth2.svg?branch=master)](http://inch-ci.org/github/simple-oauth2/simple_oauth2)
8
+ [![security](https://hakiri.io/github/simple-oauth2/simple_oauth2/master.svg)](https://hakiri.io/github/simple-oauth2/simple_oauth2/master)
9
+ [![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/simple-oauth2/simple_oauth2/blob/master/LICENSE)
10
+
11
+ A flexible OAuth2 server authorization and endpoints protection to your API
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler/setup'
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc 'Default: run specs.'
5
+ task default: :spec
6
+
7
+ RSpec::Core::RakeTask.new(:spec) do |config|
8
+ config.verbose = false
9
+ end
10
+
11
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'nobrainer'
6
+
7
+ group :test do
8
+ gem 'coveralls', require: false
9
+ gem 'factory_girl', '~> 4.0'
10
+ gem 'ffaker'
11
+ gem 'rack-test', require: 'rack/test'
12
+ gem 'rspec-rails', '~> 3.4'
13
+ end
14
+
15
+ gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
@@ -0,0 +1,36 @@
1
+ module Simple
2
+ module OAuth2
3
+ # Simple::OAuth2 accessors for configured classes.
4
+ module ClassAccessors
5
+ # Returns Access Token class by configured name
6
+ def access_token_class
7
+ @access_token_class ||= access_token_class_name.constantize
8
+ end
9
+
10
+ # Returns Resource Owner class by configured name
11
+ def resource_owner_class
12
+ @resource_owner_class ||= resource_owner_class_name.constantize
13
+ end
14
+
15
+ # Returns Client class by configured name
16
+ def client_class
17
+ @client_class ||= client_class_name.constantize
18
+ end
19
+
20
+ # Returns Access Grant class by configured name
21
+ def access_grant_class
22
+ @access_grant_class ||= access_grant_class_name.constantize
23
+ end
24
+
25
+ # Returns Token Generator class by configured name
26
+ def token_generator
27
+ token_generator_class_name.constantize
28
+ end
29
+
30
+ # Returns Scopes Validator class by configured name
31
+ def scopes_validator
32
+ scopes_validator_class_name.constantize
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ module Simple
2
+ module OAuth2
3
+ # Simple::OAuth2 default constants
4
+ module Constants
5
+ # Currently supported (by the gem) OAuth2 grant types
6
+ SUPPORTED_GRANT_TYPES = %w(password authorization_code refresh_token client_credentials).freeze
7
+
8
+ # Default OAuth2 response types
9
+ SUPPORTED_RESPONSE_TYPES = %w(code token).freeze
10
+
11
+ # Default Access Token TTL (in seconds)
12
+ DEFAULT_TOKEN_LIFETIME = 7200
13
+
14
+ # Default Authorization Code TTL (in seconds)
15
+ DEFAULT_CODE_LIFETIME = 1800
16
+
17
+ # Default realm value
18
+ DEFAULT_REALM = 'OAuth 2.0'.freeze
19
+
20
+ # Default Client class value
21
+ DEFAULT_CLIENT_CLASS = 'Client'.freeze
22
+
23
+ # Default Access Token class value
24
+ DEFAULT_ACCESS_TOKEN_CLASS = 'AccessToken'.freeze
25
+
26
+ # Default Resource Owner class value
27
+ DEFAULT_RESOURCE_OWNER_CLASS = 'User'.freeze
28
+
29
+ # Default Access Grant class value
30
+ DEFAULT_ACCESS_GRANT_CLASS = 'AccessGrant'.freeze
31
+
32
+ # Default option for generate refresh token
33
+ DEFAULT_ISSUE_REFRESH_TOKEN = false
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,169 @@
1
+ module Simple
2
+ module OAuth2
3
+ # Simple::OAuth2 configuration class.
4
+ # Contains default or customized options that would be used in OAuth2 endpoints and helpers
5
+ class Configuration
6
+ include ClassAccessors
7
+ include Constants
8
+
9
+ # The names of the classes that represents OAuth2 roles
10
+ #
11
+ # @return [String] class name
12
+ #
13
+ attr_accessor :access_token_class_name, :access_grant_class_name,
14
+ :client_class_name, :resource_owner_class_name
15
+
16
+ # Class name for the OAuth2 helper class that generates unique token values
17
+ #
18
+ # @return [String] token generator class name
19
+ #
20
+ attr_accessor :token_generator_class_name
21
+
22
+ # Class name for the OAuth2 helper class that validates requested scopes against Access Token scopes
23
+ #
24
+ # @return [String] scope validator class name
25
+ #
26
+ attr_accessor :scopes_validator_class_name
27
+
28
+ # Access Token and Authorization Code lifetime in seconds
29
+ #
30
+ # @return [Integer] lifetime in seconds
31
+ #
32
+ attr_accessor :authorization_code_lifetime, :access_token_lifetime
33
+
34
+ # OAuth2 grant types (flows) allowed to be processed
35
+ #
36
+ # @return [Array<String>] grant types
37
+ #
38
+ attr_accessor :allowed_grant_types
39
+
40
+ # OAuth2 response types (flows) allowed to be processed
41
+ #
42
+ # @return [Array<String>] response types
43
+ #
44
+ attr_accessor :allowed_response_types
45
+
46
+ # Realm value
47
+ #
48
+ # @return [String] realm
49
+ #
50
+ attr_accessor :realm
51
+
52
+ # Access Token authenticator block option for customization
53
+ attr_accessor :token_authenticator
54
+
55
+ # Resource Owner authenticator block option for customization
56
+ attr_accessor :resource_owner_authenticator
57
+
58
+ # Specifies whether to generate a Refresh Token when creating an Access Token
59
+ #
60
+ # @return [Boolean] true if need to generate refresh token
61
+ #
62
+ attr_accessor :issue_refresh_token
63
+
64
+ # Callback that would be invoked during processing of Refresh Token request for
65
+ # the original Access Token found by token value
66
+ attr_accessor :on_refresh
67
+
68
+ # Return a new instance of Configuration with default options
69
+ def initialize
70
+ setup!
71
+ end
72
+
73
+ # Accessor for Access Token authenticator block. Set it to proc
74
+ # if called with block or returns current value of the accessor.
75
+ def token_authenticator(&block)
76
+ if block_given?
77
+ instance_variable_set(:'@token_authenticator', block)
78
+ else
79
+ instance_variable_get(:'@token_authenticator')
80
+ end
81
+ end
82
+
83
+ # Accessor for Resource Owner authenticator block. Set it to proc
84
+ # if called with block or returns current value of the accessor.
85
+ def resource_owner_authenticator(&block)
86
+ if block_given?
87
+ instance_variable_set(:'@resource_owner_authenticator', block)
88
+ else
89
+ instance_variable_get(:'@resource_owner_authenticator')
90
+ end
91
+ end
92
+
93
+ # Indicates if on_refresh callback can be invoked.
94
+ #
95
+ # @return [Boolean]
96
+ # true if callback can be invoked and false in other cases
97
+ #
98
+ def on_refresh_runnable?
99
+ !on_refresh.nil? && on_refresh != :nothing
100
+ end
101
+
102
+ # Accessor for on_refresh callback. Set callback proc
103
+ # if called with block or returns current value of the accessor.
104
+ def on_refresh(&block)
105
+ if block_given?
106
+ instance_variable_set(:'@on_refresh', block)
107
+ else
108
+ instance_variable_get(:'@on_refresh')
109
+ end
110
+ end
111
+
112
+ # Default Access Token authenticator block.
113
+ # Validates token value passed with the request params
114
+ def default_token_authenticator
115
+ lambda do |request|
116
+ access_token_class.authenticate(request.access_token) || request.invalid_token!
117
+ end
118
+ end
119
+
120
+ private
121
+
122
+ # Setup configuration to default options values
123
+ def setup!
124
+ init_classes
125
+ init_authenticators
126
+ init_represents_roles
127
+
128
+ self.access_token_lifetime = DEFAULT_TOKEN_LIFETIME
129
+ self.authorization_code_lifetime = DEFAULT_CODE_LIFETIME
130
+ self.allowed_grant_types = SUPPORTED_GRANT_TYPES
131
+ self.allowed_response_types = SUPPORTED_RESPONSE_TYPES
132
+ self.issue_refresh_token = DEFAULT_ISSUE_REFRESH_TOKEN
133
+ self.on_refresh = :nothing
134
+
135
+ self.realm = DEFAULT_REALM
136
+ end
137
+
138
+ # Default Resource Owner authenticator block
139
+ def default_resource_owner_authenticator
140
+ lambda do |_request|
141
+ raise(
142
+ 'Resource Owner find failed due to '\
143
+ 'Simple::OAuth2.configure.resource_owner_authenticator being unconfigured.'
144
+ )
145
+ end
146
+ end
147
+
148
+ # Sets OAuth2 helpers classes to gem defaults
149
+ def init_classes
150
+ self.token_generator_class_name = Simple::OAuth2::UniqToken.name
151
+ self.scopes_validator_class_name = Simple::OAuth2::Scopes.name
152
+ end
153
+
154
+ # Sets authenticators to gem defaults
155
+ def init_authenticators
156
+ self.token_authenticator = default_token_authenticator
157
+ self.resource_owner_authenticator = default_resource_owner_authenticator
158
+ end
159
+
160
+ # Sets OAuth2 represents roles
161
+ def init_represents_roles
162
+ self.access_token_class_name = DEFAULT_ACCESS_TOKEN_CLASS
163
+ self.resource_owner_class_name = DEFAULT_RESOURCE_OWNER_CLASS
164
+ self.client_class_name = DEFAULT_CLIENT_CLASS
165
+ self.access_grant_class_name = DEFAULT_ACCESS_GRANT_CLASS
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,64 @@
1
+ module Simple
2
+ module OAuth2
3
+ module Generators
4
+ # Authorization generator class
5
+ # Processes the request by required Response Type and builds the response
6
+ class Authorization < Base
7
+ class << self
8
+ # Generates Authorization Response based on the request
9
+ #
10
+ # @return [Simple::OAuth2::Responses] response
11
+ #
12
+ def generate_for(env, &_block)
13
+ authorization = Rack::OAuth2::Server::Authorize.new do |request, response|
14
+ request.unsupported_response_type! unless allowed_types.include?(request.response_type.to_s)
15
+
16
+ if block_given?
17
+ yield request, response
18
+ else
19
+ execute_default(request, response)
20
+ end
21
+ end
22
+
23
+ Simple::OAuth2::Responses.new(authorization.call(env))
24
+ rescue Rack::OAuth2::Server::Authorize::BadRequest => error
25
+ error_response(error)
26
+ end
27
+
28
+ private
29
+
30
+ # Returns error Rack::Response
31
+ def error_response(error)
32
+ response = Rack::Response.new
33
+ response.status = error.status
34
+ response.header['Content-Type'] = 'application/json'
35
+ response.write(JSON.dump(Rack::OAuth2::Util.compact_hash(error.protocol_params)))
36
+
37
+ Simple::OAuth2::Responses.new(response.finish)
38
+ end
39
+
40
+ # Runs default Simple::OAuth2 functionality for Authorization endpoint
41
+ #
42
+ # @param request [Rack::Request] request object
43
+ # @param response [Rack::Response] response object
44
+ #
45
+ def execute_default(request, response)
46
+ find_strategy(request.response_type).process(request, response)
47
+ response.approve!
48
+ response
49
+ end
50
+
51
+ # Returns Simple::OAuth2 strategy class by Response Type
52
+ #
53
+ # @param response_type [Symbol] response type value
54
+ #
55
+ # @return [Code, Token] strategy class
56
+ #
57
+ def find_strategy(response_type)
58
+ "Simple::OAuth2::Strategies::#{response_type.to_s.classify}".constantize
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,31 @@
1
+ module Simple
2
+ module OAuth2
3
+ module Generators
4
+ # Base class for Simple::OAuth2 generators
5
+ class Base
6
+ class << self
7
+ # Allowed grant types from the Simple::OAuth2 configuration
8
+ #
9
+ # @return [Array] allowed grant types
10
+ #
11
+ def allowed_grants
12
+ config.allowed_grant_types
13
+ end
14
+
15
+ # Allowed response types from the Simple::OAuth2 configuration
16
+ #
17
+ # @return [Array] allowed response types
18
+ #
19
+ def allowed_types
20
+ config.allowed_response_types
21
+ end
22
+
23
+ # Short getter for Simple::OAuth2 configuration.
24
+ def config
25
+ Simple::OAuth2.config
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,71 @@
1
+ module Simple
2
+ module OAuth2
3
+ module Generators
4
+ # Token generator class.
5
+ # Processes the request by required Grant Type and builds the response
6
+ class Token < Base
7
+ class << self
8
+ # Generates Token Response based on the request
9
+ #
10
+ # @return [Simple::OAuth2::Responses] response
11
+ #
12
+ def generate_for(env, &_block)
13
+ token = Rack::OAuth2::Server::Token.new do |request, response|
14
+ request.unsupported_grant_type! unless allowed_grants.include?(request.grant_type.to_s)
15
+
16
+ if block_given?
17
+ yield(request, response)
18
+ else
19
+ execute_default(request, response)
20
+ end
21
+ end
22
+
23
+ Simple::OAuth2::Responses.new(token.call(env))
24
+ end
25
+
26
+ # OAuth 2.0 Token Revocation - http://tools.ietf.org/html/rfc7009
27
+ #
28
+ # @return [Response] with HTTP status code 200
29
+ #
30
+ def revoke(token, env)
31
+ access_token = config.access_token_class.authenticate(token, 'refresh_token')
32
+
33
+ if access_token
34
+ request = Rack::OAuth2::Server::Token::Request.new(env)
35
+
36
+ # The authorization server, if applicable, first authenticates the client
37
+ # and checks its ownership of the provided token.
38
+ client = Simple::OAuth2::Strategies::Base.authenticate_client(request) || request.invalid_client!
39
+ client.id == access_token.client.id && access_token.revoke!
40
+ end
41
+ # The authorization server responds with HTTP status code 200 if the token
42
+ # has been revoked successfully or if the client submitted an invalid token
43
+ [200, {}, []]
44
+ end
45
+
46
+ private
47
+
48
+ # Runs default Simple::OAuth2 functionality for Token endpoint.
49
+ #
50
+ # @param request [Rack::Request] request object
51
+ # @param response [Rack::Response] response object
52
+ #
53
+ def execute_default(request, response)
54
+ strategy = find_strategy(request.grant_type) || request.invalid_grant!
55
+ response.access_token = strategy.process(request)
56
+ end
57
+
58
+ # Returns Simple::OAuth2 strategy class by Grant Type
59
+ #
60
+ # @param grant_type [Symbol] grant type value
61
+ #
62
+ # @return [Password, RefreshToken, AuthorizationCode] strategy class
63
+ #
64
+ def find_strategy(grant_type)
65
+ "Simple::OAuth2::Strategies::#{grant_type.to_s.camelize}".constantize
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,40 @@
1
+ module Simple
2
+ module OAuth2
3
+ # Set of Simple::OAuth2 helpers
4
+ module Helpers
5
+ # Adds OAuth2 AccessToken protection for routes
6
+ #
7
+ # @param scopes [Array<String, Symbol>] set of scopes required to access the endpoint
8
+ #
9
+ # @raise [Rack::OAuth2::Server::Resource::Bearer::Unauthorized] invalid AccessToken value
10
+ # @raise [Rack::OAuth2::Server::Resource::Bearer::Forbidden]
11
+ # AccessToken expired, revoked or does't have required scopes
12
+ #
13
+ def access_token_required!(*scopes)
14
+ raise Rack::OAuth2::Server::Resource::Bearer::Unauthorized if current_access_token.nil?
15
+ raise Rack::OAuth2::Server::Resource::Bearer::Forbidden unless valid_access_token?(scopes)
16
+ end
17
+
18
+ # Returns ResourceOwner from the AccessToken found by access_token value passed with the request
19
+ def current_resource_owner
20
+ @current_resource_owner ||= instance_eval(&Simple::OAuth2.config.resource_owner_authenticator)
21
+ end
22
+
23
+ # Returns AccessToken instance found by access_token value passed with the request
24
+ def current_access_token
25
+ @current_access_token ||= request.env[Rack::OAuth2::Server::Resource::ACCESS_TOKEN]
26
+ end
27
+
28
+ private
29
+
30
+ # Validate current access token not to be expired or revoked and has all the requested scopes
31
+ #
32
+ # @return [Boolean] true if current_access_token not expired, not revoked and scopes match
33
+ #
34
+ def valid_access_token?(scopes)
35
+ !current_access_token.revoked? && !current_access_token.expired? &&
36
+ Simple::OAuth2.config.scopes_validator.valid?(current_access_token.scopes, scopes)
37
+ end
38
+ end
39
+ end
40
+ end