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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +25 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +26 -0
- data/.hound.yml +4 -0
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +12 -0
- data/.travis.yml +31 -0
- data/Gemfile +18 -0
- data/LICENSE +21 -0
- data/README.md +11 -0
- data/Rakefile +11 -0
- data/gemfiles/nobrainer.rb +15 -0
- data/lib/simple_oauth2/configuration/class_accessors.rb +36 -0
- data/lib/simple_oauth2/configuration/constants.rb +36 -0
- data/lib/simple_oauth2/configuration.rb +169 -0
- data/lib/simple_oauth2/generators/authorization.rb +64 -0
- data/lib/simple_oauth2/generators/base.rb +31 -0
- data/lib/simple_oauth2/generators/token.rb +71 -0
- data/lib/simple_oauth2/helpers.rb +40 -0
- data/lib/simple_oauth2/mixins/nobrainer/access_grant.rb +62 -0
- data/lib/simple_oauth2/mixins/nobrainer/access_token.rb +98 -0
- data/lib/simple_oauth2/mixins/nobrainer/client.rb +43 -0
- data/lib/simple_oauth2/resource/bearer.rb +20 -0
- data/lib/simple_oauth2/responses.rb +62 -0
- data/lib/simple_oauth2/scopes.rb +59 -0
- data/lib/simple_oauth2/strategies/authorization_code.rb +22 -0
- data/lib/simple_oauth2/strategies/base.rb +61 -0
- data/lib/simple_oauth2/strategies/client_credentials.rb +21 -0
- data/lib/simple_oauth2/strategies/code.rb +25 -0
- data/lib/simple_oauth2/strategies/password.rb +21 -0
- data/lib/simple_oauth2/strategies/refresh_token.rb +53 -0
- data/lib/simple_oauth2/strategies/token.rb +24 -0
- data/lib/simple_oauth2/uniq_token.rb +20 -0
- data/lib/simple_oauth2/version.rb +26 -0
- data/lib/simple_oauth2.rb +62 -0
- data/logo.png +0 -0
- data/simple_oauth2.gemspec +22 -0
- data/spec/configuration/config_spec.rb +181 -0
- data/spec/configuration/version_spec.rb +11 -0
- data/spec/dummy/endpoints/authorization.rb +15 -0
- data/spec/dummy/endpoints/custom_authorization.rb +21 -0
- data/spec/dummy/endpoints/custom_token.rb +21 -0
- data/spec/dummy/endpoints/status.rb +51 -0
- data/spec/dummy/endpoints/token.rb +22 -0
- data/spec/dummy/orm/nobrainer/app/config/db.rb +8 -0
- data/spec/dummy/orm/nobrainer/app/models/access_grant.rb +3 -0
- data/spec/dummy/orm/nobrainer/app/models/access_token.rb +3 -0
- data/spec/dummy/orm/nobrainer/app/models/client.rb +3 -0
- data/spec/dummy/orm/nobrainer/app/models/user.rb +11 -0
- data/spec/dummy/orm/nobrainer/app/twitter.rb +51 -0
- data/spec/dummy/orm/nobrainer/config.ru +37 -0
- data/spec/dummy/simple_oauth2_config.rb +7 -0
- data/spec/requests/flows/authorization_code_spec.rb +177 -0
- data/spec/requests/flows/client_credentials_spec.rb +163 -0
- data/spec/requests/flows/code_spec.rb +98 -0
- data/spec/requests/flows/password_spec.rb +183 -0
- data/spec/requests/flows/refresh_token_spec.rb +282 -0
- data/spec/requests/flows/token_spec.rb +113 -0
- data/spec/requests/protected_resources_spec.rb +65 -0
- data/spec/requests/revoke_token_spec.rb +90 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/support/helper.rb +11 -0
- 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
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
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
|
+

|
2
|
+
|
3
|
+
[](https://travis-ci.org/simple-oauth2/simple_oauth2)
|
4
|
+
[](https://gemnasium.com/github.com/simple-oauth2/simple_oauth2)
|
5
|
+
[](https://coveralls.io/github/simple-oauth2/simple_oauth2?branch=master)
|
6
|
+
[](https://codeclimate.com/github/simple-oauth2/simple_oauth2)
|
7
|
+
[](http://inch-ci.org/github/simple-oauth2/simple_oauth2)
|
8
|
+
[](https://hakiri.io/github/simple-oauth2/simple_oauth2/master)
|
9
|
+
[](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,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
|