haveapi 0.17.0 → 0.18.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/haveapi.gemspec +2 -1
- data/lib/haveapi/authentication/base.rb +10 -0
- data/lib/haveapi/authentication/chain.rb +2 -0
- data/lib/haveapi/authentication/oauth2/config.rb +143 -0
- data/lib/haveapi/authentication/oauth2/provider.rb +231 -0
- data/lib/haveapi/authentication/oauth2.rb +9 -0
- data/lib/haveapi/client_examples/curl.rb +3 -0
- data/lib/haveapi/client_examples/fs_client.rb +3 -0
- data/lib/haveapi/client_examples/http.rb +19 -0
- data/lib/haveapi/client_examples/js_client.rb +3 -0
- data/lib/haveapi/client_examples/php_client.rb +3 -0
- data/lib/haveapi/client_examples/ruby_cli.rb +3 -0
- data/lib/haveapi/client_examples/ruby_client.rb +3 -0
- data/lib/haveapi/server.rb +7 -0
- data/lib/haveapi/version.rb +1 -1
- data/lib/haveapi/views/version_page/auth_body.erb +7 -0
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a503deac250571b471c672f113a2470e24ebf575ec19b09d44d1d48c210bf50
|
4
|
+
data.tar.gz: 300d414e67b3d2083c0c6d352e1817274e7ed729d099b6f814aa5fd03bd81ce8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e7d0ecf8a43a49e8bf7dca76286f6dc43cb22c65794d080e2d74b7f5ba1e39ccb6d1d1800229f925b26df6dcbad8f8bb5eb74ac70c50741450c95a5ad9f893d
|
7
|
+
data.tar.gz: 10581d63837d9a8a2fb19625dc8b61b1217fe0c4fe55dac6376190e45e482d5786ca0b32cc7d5bcd6c100f16871a5f27c789bfcdd5ea4edc5c63cadec5ad03bb
|
data/haveapi.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_runtime_dependency 'rake'
|
24
24
|
s.add_runtime_dependency 'github-markdown'
|
25
25
|
s.add_runtime_dependency 'nesty', '~> 1.0'
|
26
|
-
s.add_runtime_dependency 'haveapi-client', '~> 0.
|
26
|
+
s.add_runtime_dependency 'haveapi-client', '~> 0.18.1'
|
27
27
|
s.add_runtime_dependency 'mail'
|
28
|
+
s.add_runtime_dependency 'rack-oauth2', '~> 2.2.0'
|
28
29
|
end
|
@@ -13,6 +13,10 @@ module HaveAPI
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
def self.inherited(subclass)
|
17
|
+
subclass.send(:instance_variable_set, '@auth_method', @auth_method)
|
18
|
+
end
|
19
|
+
|
16
20
|
# @return [Symbol]
|
17
21
|
attr_reader :name
|
18
22
|
|
@@ -23,6 +27,12 @@ module HaveAPI
|
|
23
27
|
setup
|
24
28
|
end
|
25
29
|
|
30
|
+
# Register custom path handlers in sinatra
|
31
|
+
# @param sinatra [Sinatra::Base]
|
32
|
+
# @param prefix [String]
|
33
|
+
def register_routes(sinatra, prefix)
|
34
|
+
end
|
35
|
+
|
26
36
|
# @return [Module, nil]
|
27
37
|
def resource_module
|
28
38
|
nil
|
@@ -99,6 +99,8 @@ module HaveAPI::Authentication
|
|
99
99
|
instance = p.new(@server, v)
|
100
100
|
@instances[v] << instance
|
101
101
|
|
102
|
+
@server.add_auth_routes(v, instance, prefix: instance.name.to_s)
|
103
|
+
|
102
104
|
if resource_module = instance.resource_module
|
103
105
|
@server.add_auth_module(
|
104
106
|
v,
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module HaveAPI::Authentication
|
2
|
+
module OAuth2
|
3
|
+
# Config passed to the OAuth2 provider
|
4
|
+
#
|
5
|
+
# Create your own subclass and pass it to {HaveAPI::Authentication::OAuth2.with_config}.
|
6
|
+
# The created provider can then be added to authentication chain.
|
7
|
+
#
|
8
|
+
# In general, it is up to the implementation to provide the authentication flow
|
9
|
+
# -- render HTML page in {#render_authorize_page} and then process it in
|
10
|
+
# {#handle_post_authorize}. The implementation must also handle generation
|
11
|
+
# of all needed tokens, their persistence and validity checking.
|
12
|
+
class Config
|
13
|
+
def initialize(provider, server, v)
|
14
|
+
@provider = provider
|
15
|
+
@server = server
|
16
|
+
@version = v
|
17
|
+
end
|
18
|
+
|
19
|
+
# Render authorization page
|
20
|
+
#
|
21
|
+
# This method can be called on both GET and POST requests, e.g. if the user
|
22
|
+
# provided incorrect credentials or if there are multiple authentication
|
23
|
+
# steps.
|
24
|
+
#
|
25
|
+
# It should return full HTML page that will be sent to the user. The page
|
26
|
+
# usually contains a login form.
|
27
|
+
#
|
28
|
+
# @param oauth2_request [Rack::OAuth2::Server::Authorize::Request]
|
29
|
+
# @param sinatra_params [Hash] request params
|
30
|
+
# @param client [Client]
|
31
|
+
# @param auth_result [AuthResult, nil]
|
32
|
+
# @return [String] HTML
|
33
|
+
def render_authorize_page(oauth2_request, sinatra_params, client, auth_result: nil)
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
# Handle POST requests made from {#render_authorize_page}
|
38
|
+
#
|
39
|
+
# Process form data and return {AuthResult} or nil. When nil is returned
|
40
|
+
# the authorization process is aborted and the user is redirected back
|
41
|
+
# to the client.
|
42
|
+
#
|
43
|
+
# @param sinatra_request [Sinatra::Request]
|
44
|
+
# @param sinatra_params [Hash] request params
|
45
|
+
# @param oauth2_request [Rack::OAuth2::Server::Authorize::Request]
|
46
|
+
# @param client [Client]
|
47
|
+
# @return [AuthResult, nil]
|
48
|
+
def handle_post_authorize(sinatra_request, sinatra_params, oauth2_request, client)
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get oauth2 authorization code
|
53
|
+
#
|
54
|
+
# Called when the authentication is successful and complete. This method
|
55
|
+
# must generate and return authorization_code which is then sent to the
|
56
|
+
# client. It is up to the API implementation to persist the code.
|
57
|
+
#
|
58
|
+
# @param auth_res [AuthResult] value returned by {#handle_post_authorize}
|
59
|
+
# @return [String]
|
60
|
+
def get_authorization_code(auth_res)
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get access token, its expiration date and optionally a refresh token
|
65
|
+
#
|
66
|
+
# The client has used the authorization_code returned by {#get_authorization_code}
|
67
|
+
# and now requests its access token. It is up to the implementation to create
|
68
|
+
# and persist the tokens. The authorization code should be invalidated.
|
69
|
+
#
|
70
|
+
# @param authorization [Authorization]
|
71
|
+
# @param sinatra_request [Sinatra::Request]
|
72
|
+
# @return [Array] access token, expiration date and optional refresh token
|
73
|
+
def get_tokens(authorization, sinatra_request)
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
# Refresh access token and optionally generate new refresh token
|
78
|
+
#
|
79
|
+
# The implementation should invalidate the current tokens and generate
|
80
|
+
# and persist new ones.
|
81
|
+
#
|
82
|
+
# @param authorization [Authorization]
|
83
|
+
# @param sinatra_request [Sinatra::Request]
|
84
|
+
# @return [Array] access token, expiration date and optional refresh token
|
85
|
+
def refresh_tokens(authorization, sinatra_request)
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
# Find client by ID
|
90
|
+
# @param client_id [String]
|
91
|
+
# @return [Client, nil]
|
92
|
+
def find_client_by_id(client_id)
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
# Find authorization by code
|
97
|
+
# @param client [Client]
|
98
|
+
# @param code [String]
|
99
|
+
# @return [Authorization, nil]
|
100
|
+
def find_authorization_by_code(client, code)
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
# Find authorization by refresh token
|
105
|
+
# @param client [Client]
|
106
|
+
# @param refresh_token [String]
|
107
|
+
# @return [Authorization, nil]
|
108
|
+
def find_authorization_by_refresh_token(client, refresh_token)
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# Find user by the bearer token sent in HTTP header or as a query parameter
|
113
|
+
# @param sinatra_request [Sinatra::Request]
|
114
|
+
# @param access_token [String]
|
115
|
+
# @return [Object, nil] user
|
116
|
+
def find_user_by_access_token(request, access_token)
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
# Path to the authorization endpoint on this API
|
121
|
+
# @return [String]
|
122
|
+
def authorize_path
|
123
|
+
@provider.authorize_path
|
124
|
+
end
|
125
|
+
|
126
|
+
# Parameters needed for the authorization process
|
127
|
+
#
|
128
|
+
# Use these in {#render_authorization_page}, put them e.g. in hidden form
|
129
|
+
# fields.
|
130
|
+
#
|
131
|
+
# @return [Hash<String, String>]
|
132
|
+
def oauth2_params(req)
|
133
|
+
{
|
134
|
+
client_id: req.client_id,
|
135
|
+
response_type: req.response_type,
|
136
|
+
redirect_uri: req.redirect_uri,
|
137
|
+
scope: req.scope.join(' '),
|
138
|
+
state: req.state,
|
139
|
+
}
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'haveapi/authentication/base'
|
2
|
+
require 'rack/oauth2'
|
3
|
+
|
4
|
+
module HaveAPI::Authentication
|
5
|
+
module OAuth2
|
6
|
+
# Abstract class describing the client and what methods it must respond to
|
7
|
+
class Client
|
8
|
+
# @return [String]
|
9
|
+
attr_reader :client_id
|
10
|
+
|
11
|
+
# @return [String]
|
12
|
+
attr_reader :redirect_uri
|
13
|
+
|
14
|
+
# @param client_secret [String]
|
15
|
+
# @return [Boolean]
|
16
|
+
def check_secret(client_secret)
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Abstract class describing the authentication result and what methods it must respond to
|
22
|
+
class AuthResult
|
23
|
+
# True of the user was authenticated
|
24
|
+
# @return [Boolean]
|
25
|
+
attr_reader :authenticated
|
26
|
+
|
27
|
+
# True if the authentication process is complete, false if other steps are needed
|
28
|
+
# @return [Boolean]
|
29
|
+
attr_reader :complete
|
30
|
+
|
31
|
+
# True if the user asked to cancel the authorization process
|
32
|
+
# @return [Boolean]
|
33
|
+
attr_reader :cancel
|
34
|
+
end
|
35
|
+
|
36
|
+
# Abstract class describing ongoing authorization and what methods it must respond to
|
37
|
+
class Authorization
|
38
|
+
# @return [String]
|
39
|
+
attr_reader :redirect_uri
|
40
|
+
|
41
|
+
# @param redirect_uri [String]
|
42
|
+
# @return [Boolean]
|
43
|
+
def check_code_validity(redirect_uri)
|
44
|
+
raise NotImplementedError
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# OAuth2 authentication and authorization provider
|
49
|
+
#
|
50
|
+
# Must be configured with {Config} using {OAuth2.with_config}.
|
51
|
+
class Provider < Base
|
52
|
+
auth_method :oauth2
|
53
|
+
|
54
|
+
# Configure the OAuth2 provider
|
55
|
+
# @param cfg [Config]
|
56
|
+
def self.with_config(cfg)
|
57
|
+
Module.new do
|
58
|
+
define_singleton_method(:new) do |*args|
|
59
|
+
Provider.new(*args, cfg)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [String]
|
65
|
+
attr_reader :authorize_path
|
66
|
+
|
67
|
+
# @return [Config]
|
68
|
+
attr_reader :config
|
69
|
+
|
70
|
+
def initialize(server, v, cfg)
|
71
|
+
@config = cfg.new(self, server, v)
|
72
|
+
super(server, v)
|
73
|
+
end
|
74
|
+
|
75
|
+
def register_routes(sinatra, prefix)
|
76
|
+
@authorize_path = File.join(prefix, 'authorize')
|
77
|
+
@token_path = File.join(prefix, 'token')
|
78
|
+
that = self
|
79
|
+
|
80
|
+
sinatra.get @authorize_path do
|
81
|
+
that.authorization_endpoint(self).call(request.env)
|
82
|
+
end
|
83
|
+
|
84
|
+
sinatra.post @authorize_path do
|
85
|
+
that.authorization_endpoint(self).call(request.env)
|
86
|
+
end
|
87
|
+
|
88
|
+
sinatra.post @token_path do
|
89
|
+
that.token_endpoint(self).call(request.env)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def authenticate(request)
|
94
|
+
tokens = [
|
95
|
+
request['access_token'],
|
96
|
+
token_from_header(request)
|
97
|
+
].compact
|
98
|
+
|
99
|
+
token =
|
100
|
+
case tokens.length
|
101
|
+
when 0
|
102
|
+
nil
|
103
|
+
when 1
|
104
|
+
tokens.first
|
105
|
+
else
|
106
|
+
fail 'Too many oauth2 tokens'
|
107
|
+
end
|
108
|
+
|
109
|
+
token && config.find_user_by_access_token(request, token)
|
110
|
+
end
|
111
|
+
|
112
|
+
def token_from_header(request)
|
113
|
+
auth_header = Rack::Auth::AbstractRequest.new(request.env)
|
114
|
+
|
115
|
+
if auth_header.provided? && !auth_header.parts.first.nil? && auth_header.scheme.to_s == 'bearer'
|
116
|
+
auth_header.params
|
117
|
+
else
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def describe
|
123
|
+
desc = <<-END
|
124
|
+
OAuth2 authorization provider. While OAuth2 is not supported by HaveAPI
|
125
|
+
clients, it is possible to use your API as an authentication source.
|
126
|
+
|
127
|
+
HaveAPI partially implements RFC 6749: authorization response type "code"
|
128
|
+
and token grant types "authorization_code" and "refresh_token". Other
|
129
|
+
response and grant types are not supported at this time.
|
130
|
+
|
131
|
+
The access token can be passed as bearer token according to RFC 6750.
|
132
|
+
END
|
133
|
+
|
134
|
+
{
|
135
|
+
description: desc,
|
136
|
+
authorize_path: @authorize_path,
|
137
|
+
token_path: @token_path,
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
def authorization_endpoint(handler)
|
142
|
+
Rack::OAuth2::Server::Authorize.new do |req, res|
|
143
|
+
client = config.find_client_by_id(req.client_id)
|
144
|
+
req.bad_request! if client.nil?
|
145
|
+
|
146
|
+
res.redirect_uri = req.verify_redirect_uri!(client.redirect_uri)
|
147
|
+
|
148
|
+
if req.post?
|
149
|
+
auth_res = config.handle_post_authorize(handler.request, handler.params, req, client)
|
150
|
+
|
151
|
+
if auth_res.nil?
|
152
|
+
# Authentication failed
|
153
|
+
req.access_denied!
|
154
|
+
elsif auth_res.cancel
|
155
|
+
# Cancel the process
|
156
|
+
req.access_denied!
|
157
|
+
elsif auth_res.authenticated && auth_res.complete
|
158
|
+
# Authentication was successful
|
159
|
+
case req.response_type
|
160
|
+
when :code
|
161
|
+
res.code = config.get_authorization_code(auth_res)
|
162
|
+
when :token
|
163
|
+
req.unsupported_response_type!
|
164
|
+
end
|
165
|
+
|
166
|
+
res.approve!
|
167
|
+
elsif auth_res.authenticated && !auth_res.complete
|
168
|
+
# Continue with another authentication step
|
169
|
+
res.content_type = 'text/html'
|
170
|
+
res.write(config.render_authorize_page(req, handler.params, client, auth_result: auth_res))
|
171
|
+
else
|
172
|
+
# Authentication failed, report errors and let the user retry
|
173
|
+
res.content_type = 'text/html'
|
174
|
+
res.write(config.render_authorize_page(req, handler.params, client, auth_result: auth_res))
|
175
|
+
end
|
176
|
+
else
|
177
|
+
res.content_type = 'text/html'
|
178
|
+
res.write(config.render_authorize_page(req, handler.params, client))
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def token_endpoint(handler)
|
184
|
+
Rack::OAuth2::Server::Token.new do |req, res|
|
185
|
+
client = config.find_client_by_id(req.client_id)
|
186
|
+
req.invalid_client! if client.nil? || !client.check_secret(req.client_secret)
|
187
|
+
|
188
|
+
res.access_token =
|
189
|
+
case req.grant_type
|
190
|
+
when :authorization_code
|
191
|
+
authorization = config.find_authorization_by_code(client, req.code)
|
192
|
+
|
193
|
+
if authorization.nil? || !authorization.check_code_validity(req.redirect_uri)
|
194
|
+
req.invalid_grant!
|
195
|
+
end
|
196
|
+
|
197
|
+
access_token, expires_at, refresh_token = config.get_tokens(authorization, handler.request)
|
198
|
+
|
199
|
+
bearer_token = Rack::OAuth2::AccessToken::Bearer.new(
|
200
|
+
access_token: access_token,
|
201
|
+
expires_in: expires_at - Time.now,
|
202
|
+
)
|
203
|
+
bearer_token.refresh_token = refresh_token if refresh_token
|
204
|
+
bearer_token
|
205
|
+
|
206
|
+
when :password
|
207
|
+
req.unsupported_grant_type!
|
208
|
+
|
209
|
+
when :client_credentials
|
210
|
+
req.unsupported_grant_type!
|
211
|
+
|
212
|
+
when :refresh_token
|
213
|
+
config.find_authorization_by_refresh_token(client, req.refresh_token)
|
214
|
+
|
215
|
+
access_token, expires_at, refresh_token = config.refresh_tokens(authorization, handler.request)
|
216
|
+
|
217
|
+
bearer_token = Rack::OAuth2::AccessToken::Bearer.new(
|
218
|
+
access_token: access_token,
|
219
|
+
expires_in: expires_at - Time.now,
|
220
|
+
)
|
221
|
+
bearer_token.refresh_token = refresh_token if refresh_token
|
222
|
+
bearer_token
|
223
|
+
|
224
|
+
else
|
225
|
+
req.unsupported_grant_type!
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -36,6 +36,25 @@ Host: #{host}
|
|
36
36
|
Content-Type: application/json
|
37
37
|
|
38
38
|
#{JSON.pretty_generate({token: login})}
|
39
|
+
END
|
40
|
+
|
41
|
+
when :oauth2
|
42
|
+
<<END
|
43
|
+
# 1) Request authorization code
|
44
|
+
GET #{desc[:authorize_path]}?response_type=code&client_id=$client_id&state=$state&redirect_uri=$client_redirect_uri HTTP/1.1
|
45
|
+
Host: #{host}
|
46
|
+
|
47
|
+
# 2) The user logs in using this API
|
48
|
+
|
49
|
+
# 3) The API then redirects the user back to the client application
|
50
|
+
GET $client_redirect_uri?code=$authorization_code&state=$state
|
51
|
+
Host: client-application
|
52
|
+
|
53
|
+
# 4) The client application requests access token
|
54
|
+
POST #{desc[:token_path]}
|
55
|
+
Content-Type: application/x-www-form-urlencoded
|
56
|
+
|
57
|
+
grant_type=authorization_code&code=$authorization_code&redirect_uri=$client_redirect_uri&client_id=$client_id&client_secret=$client_secret
|
39
58
|
END
|
40
59
|
end
|
41
60
|
end
|
@@ -33,6 +33,9 @@ echo "Token = ".$api->getAuthenticationProvider()->getToken();
|
|
33
33
|
// Next time, the client can authenticate using the token directly
|
34
34
|
$api->authenticate("token", ["token" => $savedToken]);
|
35
35
|
END
|
36
|
+
|
37
|
+
when :oauth2
|
38
|
+
'// OAuth2 is not supported by HaveAPI PHP client.'
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
data/lib/haveapi/server.rb
CHANGED
@@ -576,6 +576,13 @@ module HaveAPI
|
|
576
576
|
"#{@root}v#{v}/"
|
577
577
|
end
|
578
578
|
|
579
|
+
# @param v [String] API version
|
580
|
+
# @param provider [Authentication::Base]
|
581
|
+
# @param prefix [String]
|
582
|
+
def add_auth_routes(v, provider, prefix: '')
|
583
|
+
provider.register_routes(@sinatra, "#{@root}_auth/#{prefix}")
|
584
|
+
end
|
585
|
+
|
579
586
|
def add_auth_module(v, name, mod, prefix: '')
|
580
587
|
@routes[v] ||= {authentication: {name => {resources: {}}}}
|
581
588
|
|
data/lib/haveapi/version.rb
CHANGED
@@ -10,6 +10,13 @@
|
|
10
10
|
<dt>Query parameter:</dt>
|
11
11
|
<dd><%= info[:query_parameter] %></dd>
|
12
12
|
</dl>
|
13
|
+
<% elsif name == :oauth2 %>
|
14
|
+
<dl>
|
15
|
+
<dt>Authorize path:</dt>
|
16
|
+
<dd><%= info[:authorize_path] %></dd>
|
17
|
+
<dt>Token path:</dt>
|
18
|
+
<dd><%= info[:token_path] %></dd>
|
19
|
+
</dl>
|
13
20
|
<% end %>
|
14
21
|
|
15
22
|
<% if info[:resources] %>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haveapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jakub Skokan
|
@@ -142,14 +142,14 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 0.
|
145
|
+
version: 0.18.1
|
146
146
|
type: :runtime
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 0.
|
152
|
+
version: 0.18.1
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: mail
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,6 +164,20 @@ dependencies:
|
|
164
164
|
- - ">="
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: rack-oauth2
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 2.2.0
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 2.2.0
|
167
181
|
description: Framework for creating self-describing APIs
|
168
182
|
email: jakub.skokan@vpsfree.cz
|
169
183
|
executables: []
|
@@ -193,6 +207,9 @@ files:
|
|
193
207
|
- lib/haveapi/authentication/base.rb
|
194
208
|
- lib/haveapi/authentication/basic/provider.rb
|
195
209
|
- lib/haveapi/authentication/chain.rb
|
210
|
+
- lib/haveapi/authentication/oauth2.rb
|
211
|
+
- lib/haveapi/authentication/oauth2/config.rb
|
212
|
+
- lib/haveapi/authentication/oauth2/provider.rb
|
196
213
|
- lib/haveapi/authentication/token.rb
|
197
214
|
- lib/haveapi/authentication/token/action_config.rb
|
198
215
|
- lib/haveapi/authentication/token/action_request.rb
|