simple_oauth2 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![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,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
|