authlete 1.0.21 → 1.0.22
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 +5 -5
- data/README.md +20 -20
- data/lib/authlete/authentication-server.rb +229 -229
- data/lib/authlete/model/client.rb +66 -59
- data/lib/authlete/model/scope.rb +157 -157
- data/lib/authlete/model/service-list.rb +127 -127
- data/lib/authlete/model/service.rb +851 -836
- data/lib/authlete/model/sns-credentials.rb +123 -123
- data/lib/authlete/utility.rb +98 -98
- data/lib/authlete/version.rb +1 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 76874c7e1a1d4c0ce39569f657df73d1d445df1907bfa08602eb75fae353ce79
|
4
|
+
data.tar.gz: 7ce55dd3873f5b4a79f2df58ce84da52d0c45889701820e5a711fd1d12c496ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62a1f340f9c25fb0a052ef5211dd4e0809f68a26b9a3e5e4e204dab8cbf5c22f8e5f1733ee063330b0d3d7cdbf0b92189ec3c7b5a90510de7d572f474c3f3c74
|
7
|
+
data.tar.gz: c44961fd3bead0938e2f7db4f1e980495ec4f826974d218dcb90b57870dd5348a043d9b9f2b2ca066da19918b677e435899a0166820d821c785184a4e72061f0
|
data/README.md
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
authlete-ruby-gem
|
2
|
-
=================
|
3
|
-
|
4
|
-
# Overview
|
5
|
-
|
6
|
-
Ruby library for [Authlete Web APIs](https://docs.authlete.com/).
|
7
|
-
|
8
|
-
|
9
|
-
# License
|
10
|
-
|
11
|
-
Apache License, Version 2.0
|
12
|
-
|
13
|
-
|
14
|
-
# See Also
|
15
|
-
|
16
|
-
* [Authlete Website](https://www.authlete.com/)
|
17
|
-
* [Authlete Facebook](https://www.facebook.com/authlete)
|
18
|
-
* [Authelte Twitter](https://twitter.com/authlete)
|
19
|
-
* [Authlete GitHub](https://github.com/authlete)
|
20
|
-
* [Authlete Email](mailto:support@authlete.com)
|
1
|
+
authlete-ruby-gem
|
2
|
+
=================
|
3
|
+
|
4
|
+
# Overview
|
5
|
+
|
6
|
+
Ruby library for [Authlete Web APIs](https://docs.authlete.com/).
|
7
|
+
|
8
|
+
|
9
|
+
# License
|
10
|
+
|
11
|
+
Apache License, Version 2.0
|
12
|
+
|
13
|
+
|
14
|
+
# See Also
|
15
|
+
|
16
|
+
* [Authlete Website](https://www.authlete.com/)
|
17
|
+
* [Authlete Facebook](https://www.facebook.com/authlete)
|
18
|
+
* [Authelte Twitter](https://twitter.com/authlete)
|
19
|
+
* [Authlete GitHub](https://github.com/authlete)
|
20
|
+
* [Authlete Email](mailto:support@authlete.com)
|
@@ -1,230 +1,230 @@
|
|
1
|
-
# :nodoc:
|
2
|
-
#
|
3
|
-
# Copyright (C) 2014-2018 Authlete, Inc.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
|
17
|
-
|
18
|
-
require 'rack'
|
19
|
-
|
20
|
-
|
21
|
-
module Authlete
|
22
|
-
# == Authlete::AuthenticationServer class
|
23
|
-
#
|
24
|
-
# This class is a base class for an authentication server based on Rack.
|
25
|
-
# Some method must/should be overridden by subclasses.
|
26
|
-
#
|
27
|
-
# 1. <tt>authenticate_api_call</tt>
|
28
|
-
# 2. <tt>authenticate_user</tt>
|
29
|
-
# 3. <tt>collect_claims</tt>
|
30
|
-
# 4. <tt>authentication_callback_endpoint_path</tt>
|
31
|
-
class AuthenticationServer
|
32
|
-
def initialize(app = nil)
|
33
|
-
# Accept 'app' so that this class can work as a Rack middleware
|
34
|
-
# as well as a Rack application.
|
35
|
-
@app = app
|
36
|
-
end
|
37
|
-
|
38
|
-
def call(env)
|
39
|
-
# Request
|
40
|
-
request = Rack::Request.new(env)
|
41
|
-
|
42
|
-
# If the request is not an authentication callback request.
|
43
|
-
if match_authentication_callback_request(request) == false
|
44
|
-
# If this class is used as a Rack middleware.
|
45
|
-
if @app && @app.respond_to?(:call)
|
46
|
-
# Call chain to the next Rack middleware.
|
47
|
-
return @app.call(env)
|
48
|
-
else
|
49
|
-
# 404 Not Found
|
50
|
-
return generate_not_found(request)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# Basic Authentication for the API call.
|
55
|
-
authenticated = do_authenticate_api_call(env)
|
56
|
-
if authenticated == false
|
57
|
-
# 401 Unauthorized
|
58
|
-
return generate_api_call_authentication_failure()
|
59
|
-
end
|
60
|
-
|
61
|
-
begin
|
62
|
-
# Parse the request body as AuthenticationCallbackRequest.
|
63
|
-
req = parse_authentication_callback_request(request)
|
64
|
-
rescue => e
|
65
|
-
# 400 Bad Request
|
66
|
-
return generate_authentication_callback_request_format_error(e)
|
67
|
-
end
|
68
|
-
|
69
|
-
# Prepare an empty response.
|
70
|
-
res = Authlete::Model::Response::AuthenticationCallbackResponse.new
|
71
|
-
|
72
|
-
# Let the subclass authenticate the end-user.
|
73
|
-
# When authenticated successfully, a non-nil value is returned.
|
74
|
-
subject = authenticate_user(req)
|
75
|
-
if subject.nil?
|
76
|
-
# End-user authentication failed.
|
77
|
-
# Return {"authenticated": false} to Authlete.
|
78
|
-
res.authenticated = false
|
79
|
-
return res.to_rack_response
|
80
|
-
end
|
81
|
-
|
82
|
-
# The end-user has been authenticated successfully.
|
83
|
-
res.authenticated = true
|
84
|
-
res.subject = subject
|
85
|
-
|
86
|
-
if req.claims.nil? == false && req.claims.length != 0
|
87
|
-
# Make the subclass collect values of the requested claims.
|
88
|
-
res.claims = collect_claims(req, subject)
|
89
|
-
end
|
90
|
-
|
91
|
-
# Return {"authenticated": true, ...} to Authlete.
|
92
|
-
return res.to_rack_response
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def match_authentication_callback_request(request)
|
98
|
-
request.post? &&
|
99
|
-
request.path_info == authentication_callback_endpoint_path() &&
|
100
|
-
%r{^application/json}i === request.content_type
|
101
|
-
end
|
102
|
-
|
103
|
-
def do_authenticate_api_call(env)
|
104
|
-
# API key and secret for the API call to the authentication endpoint.
|
105
|
-
api_key, api_secret = nil, nil
|
106
|
-
|
107
|
-
# Basic Authentication for the API call.
|
108
|
-
auth = Rack::Auth::Basic::Request.new(env)
|
109
|
-
|
110
|
-
if auth.provided? && auth.basic?
|
111
|
-
api_key, api_secret = *auth.credentials
|
112
|
-
end
|
113
|
-
|
114
|
-
# Let the subclass authenticate the API call.
|
115
|
-
authenticate_api_call(api_key, api_secret)
|
116
|
-
end
|
117
|
-
|
118
|
-
# 404 Not Found
|
119
|
-
def generate_not_found(request)
|
120
|
-
[
|
121
|
-
404,
|
122
|
-
{
|
123
|
-
'Content-Type' => 'text/plain'
|
124
|
-
},
|
125
|
-
[
|
126
|
-
"Not Found: #{request.request_method} #{request.path_info} (#{request.content_type})"
|
127
|
-
]
|
128
|
-
]
|
129
|
-
end
|
130
|
-
|
131
|
-
# 401 Unauthorized
|
132
|
-
def generate_api_call_authentication_failure
|
133
|
-
[
|
134
|
-
401,
|
135
|
-
{
|
136
|
-
'Content-Type' => 'text/plain',
|
137
|
-
'WWW-Authenticate' => 'Basic realm="Authentication Callback Endpoint"'
|
138
|
-
},
|
139
|
-
[
|
140
|
-
'Authentication of the API call to the authentication callback endpoint failed.'
|
141
|
-
]
|
142
|
-
]
|
143
|
-
end
|
144
|
-
|
145
|
-
# 400 Bad Request
|
146
|
-
def generate_authentication_callback_request_format_error(exception)
|
147
|
-
[
|
148
|
-
400,
|
149
|
-
{
|
150
|
-
'Content-Type' => 'text/plain',
|
151
|
-
},
|
152
|
-
[
|
153
|
-
"The format of the authentication callback request was wrong: #{exception.to_s}"
|
154
|
-
]
|
155
|
-
]
|
156
|
-
end
|
157
|
-
|
158
|
-
def parse_authentication_callback_request(request)
|
159
|
-
# In case someone has already read it.
|
160
|
-
request.body.rewind
|
161
|
-
|
162
|
-
# JSON
|
163
|
-
json = request.body.read
|
164
|
-
|
165
|
-
# Parse the authentication callback request.
|
166
|
-
Authlete::Model::Request::AuthenticationCallbackRequest.parse(json)
|
167
|
-
end
|
168
|
-
|
169
|
-
protected
|
170
|
-
|
171
|
-
# Authenticate the API call to the authentication callback endpoint
|
172
|
-
# from Authlete. Subclasses must override this method. This default
|
173
|
-
# implementation returns false, meaning 'unauthorized API call'.
|
174
|
-
#
|
175
|
-
# The argument of this method is the API key and the API secret that
|
176
|
-
# the caller has presented. When the pair of the API credentials is
|
177
|
-
# valid, return true. Otherwise, return false.
|
178
|
-
def authenticate_api_call(api_key, api_secret)
|
179
|
-
# Unauthorized API call.
|
180
|
-
false
|
181
|
-
end
|
182
|
-
|
183
|
-
# Authenticate the end-user. Subclasses must override this method.
|
184
|
-
# This default implementation returns nil, meaning 'invalid end-user'.
|
185
|
-
#
|
186
|
-
# The argument of this method is an instance of
|
187
|
-
# <tt>Authlete::Model::Request::AuthenticationCallbackRequest</tt>.
|
188
|
-
# When the end-user is successfully authenticated, this method must
|
189
|
-
# return a unique identifier (= subject) of the end-user. Otherwise,
|
190
|
-
# nil must be returned to indicate authentication failure.
|
191
|
-
def authenticate_user(req)
|
192
|
-
# Invalid end-user.
|
193
|
-
nil
|
194
|
-
end
|
195
|
-
|
196
|
-
# Collect claim values of the end-user. Subclasses should override this
|
197
|
-
# method. This default implementation returns nil, meaning 'no claim values'.
|
198
|
-
#
|
199
|
-
# The argument of this method is an instance of
|
200
|
-
# <tt>Authlete::Model::Request::AuthenticationCallbackRequest</tt> and the subject
|
201
|
-
# which has been returned from the preceding call of <tt>authenticate_user</tt>
|
202
|
-
# method.
|
203
|
-
#
|
204
|
-
# 'Claim' is a piece of information about an end-user. A subclass should
|
205
|
-
# collect values of requested claims (<tt>req.claims</tt>) as many as
|
206
|
-
# possible and format them in JSON format like below.
|
207
|
-
#
|
208
|
-
# {
|
209
|
-
# "name": "Takahiko Kawasaki",
|
210
|
-
# "gender": "male"
|
211
|
-
# }
|
212
|
-
#
|
213
|
-
# Collected claim values are used to generate an {ID token}
|
214
|
-
# [http://openid.net/specs/openid-connect-core-1_0.html#IDToken].
|
215
|
-
#
|
216
|
-
# If no claim values are available, or if you don't want to provide any
|
217
|
-
# claim value, return nil.
|
218
|
-
def collect_claims(req, subject)
|
219
|
-
# No claim values.
|
220
|
-
nil
|
221
|
-
end
|
222
|
-
|
223
|
-
# Get the path of the authentication callback endpoint. This default
|
224
|
-
# implementation returns '/authentication'. Subclasses may override
|
225
|
-
# this method to change the path.
|
226
|
-
def authentication_callback_endpoint_path
|
227
|
-
'/authentication'
|
228
|
-
end
|
229
|
-
end
|
1
|
+
# :nodoc:
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014-2018 Authlete, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
|
18
|
+
require 'rack'
|
19
|
+
|
20
|
+
|
21
|
+
module Authlete
|
22
|
+
# == Authlete::AuthenticationServer class
|
23
|
+
#
|
24
|
+
# This class is a base class for an authentication server based on Rack.
|
25
|
+
# Some method must/should be overridden by subclasses.
|
26
|
+
#
|
27
|
+
# 1. <tt>authenticate_api_call</tt>
|
28
|
+
# 2. <tt>authenticate_user</tt>
|
29
|
+
# 3. <tt>collect_claims</tt>
|
30
|
+
# 4. <tt>authentication_callback_endpoint_path</tt>
|
31
|
+
class AuthenticationServer
|
32
|
+
def initialize(app = nil)
|
33
|
+
# Accept 'app' so that this class can work as a Rack middleware
|
34
|
+
# as well as a Rack application.
|
35
|
+
@app = app
|
36
|
+
end
|
37
|
+
|
38
|
+
def call(env)
|
39
|
+
# Request
|
40
|
+
request = Rack::Request.new(env)
|
41
|
+
|
42
|
+
# If the request is not an authentication callback request.
|
43
|
+
if match_authentication_callback_request(request) == false
|
44
|
+
# If this class is used as a Rack middleware.
|
45
|
+
if @app && @app.respond_to?(:call)
|
46
|
+
# Call chain to the next Rack middleware.
|
47
|
+
return @app.call(env)
|
48
|
+
else
|
49
|
+
# 404 Not Found
|
50
|
+
return generate_not_found(request)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Basic Authentication for the API call.
|
55
|
+
authenticated = do_authenticate_api_call(env)
|
56
|
+
if authenticated == false
|
57
|
+
# 401 Unauthorized
|
58
|
+
return generate_api_call_authentication_failure()
|
59
|
+
end
|
60
|
+
|
61
|
+
begin
|
62
|
+
# Parse the request body as AuthenticationCallbackRequest.
|
63
|
+
req = parse_authentication_callback_request(request)
|
64
|
+
rescue => e
|
65
|
+
# 400 Bad Request
|
66
|
+
return generate_authentication_callback_request_format_error(e)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Prepare an empty response.
|
70
|
+
res = Authlete::Model::Response::AuthenticationCallbackResponse.new
|
71
|
+
|
72
|
+
# Let the subclass authenticate the end-user.
|
73
|
+
# When authenticated successfully, a non-nil value is returned.
|
74
|
+
subject = authenticate_user(req)
|
75
|
+
if subject.nil?
|
76
|
+
# End-user authentication failed.
|
77
|
+
# Return {"authenticated": false} to Authlete.
|
78
|
+
res.authenticated = false
|
79
|
+
return res.to_rack_response
|
80
|
+
end
|
81
|
+
|
82
|
+
# The end-user has been authenticated successfully.
|
83
|
+
res.authenticated = true
|
84
|
+
res.subject = subject
|
85
|
+
|
86
|
+
if req.claims.nil? == false && req.claims.length != 0
|
87
|
+
# Make the subclass collect values of the requested claims.
|
88
|
+
res.claims = collect_claims(req, subject)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Return {"authenticated": true, ...} to Authlete.
|
92
|
+
return res.to_rack_response
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def match_authentication_callback_request(request)
|
98
|
+
request.post? &&
|
99
|
+
request.path_info == authentication_callback_endpoint_path() &&
|
100
|
+
%r{^application/json}i === request.content_type
|
101
|
+
end
|
102
|
+
|
103
|
+
def do_authenticate_api_call(env)
|
104
|
+
# API key and secret for the API call to the authentication endpoint.
|
105
|
+
api_key, api_secret = nil, nil
|
106
|
+
|
107
|
+
# Basic Authentication for the API call.
|
108
|
+
auth = Rack::Auth::Basic::Request.new(env)
|
109
|
+
|
110
|
+
if auth.provided? && auth.basic?
|
111
|
+
api_key, api_secret = *auth.credentials
|
112
|
+
end
|
113
|
+
|
114
|
+
# Let the subclass authenticate the API call.
|
115
|
+
authenticate_api_call(api_key, api_secret)
|
116
|
+
end
|
117
|
+
|
118
|
+
# 404 Not Found
|
119
|
+
def generate_not_found(request)
|
120
|
+
[
|
121
|
+
404,
|
122
|
+
{
|
123
|
+
'Content-Type' => 'text/plain'
|
124
|
+
},
|
125
|
+
[
|
126
|
+
"Not Found: #{request.request_method} #{request.path_info} (#{request.content_type})"
|
127
|
+
]
|
128
|
+
]
|
129
|
+
end
|
130
|
+
|
131
|
+
# 401 Unauthorized
|
132
|
+
def generate_api_call_authentication_failure
|
133
|
+
[
|
134
|
+
401,
|
135
|
+
{
|
136
|
+
'Content-Type' => 'text/plain',
|
137
|
+
'WWW-Authenticate' => 'Basic realm="Authentication Callback Endpoint"'
|
138
|
+
},
|
139
|
+
[
|
140
|
+
'Authentication of the API call to the authentication callback endpoint failed.'
|
141
|
+
]
|
142
|
+
]
|
143
|
+
end
|
144
|
+
|
145
|
+
# 400 Bad Request
|
146
|
+
def generate_authentication_callback_request_format_error(exception)
|
147
|
+
[
|
148
|
+
400,
|
149
|
+
{
|
150
|
+
'Content-Type' => 'text/plain',
|
151
|
+
},
|
152
|
+
[
|
153
|
+
"The format of the authentication callback request was wrong: #{exception.to_s}"
|
154
|
+
]
|
155
|
+
]
|
156
|
+
end
|
157
|
+
|
158
|
+
def parse_authentication_callback_request(request)
|
159
|
+
# In case someone has already read it.
|
160
|
+
request.body.rewind
|
161
|
+
|
162
|
+
# JSON
|
163
|
+
json = request.body.read
|
164
|
+
|
165
|
+
# Parse the authentication callback request.
|
166
|
+
Authlete::Model::Request::AuthenticationCallbackRequest.parse(json)
|
167
|
+
end
|
168
|
+
|
169
|
+
protected
|
170
|
+
|
171
|
+
# Authenticate the API call to the authentication callback endpoint
|
172
|
+
# from Authlete. Subclasses must override this method. This default
|
173
|
+
# implementation returns false, meaning 'unauthorized API call'.
|
174
|
+
#
|
175
|
+
# The argument of this method is the API key and the API secret that
|
176
|
+
# the caller has presented. When the pair of the API credentials is
|
177
|
+
# valid, return true. Otherwise, return false.
|
178
|
+
def authenticate_api_call(api_key, api_secret)
|
179
|
+
# Unauthorized API call.
|
180
|
+
false
|
181
|
+
end
|
182
|
+
|
183
|
+
# Authenticate the end-user. Subclasses must override this method.
|
184
|
+
# This default implementation returns nil, meaning 'invalid end-user'.
|
185
|
+
#
|
186
|
+
# The argument of this method is an instance of
|
187
|
+
# <tt>Authlete::Model::Request::AuthenticationCallbackRequest</tt>.
|
188
|
+
# When the end-user is successfully authenticated, this method must
|
189
|
+
# return a unique identifier (= subject) of the end-user. Otherwise,
|
190
|
+
# nil must be returned to indicate authentication failure.
|
191
|
+
def authenticate_user(req)
|
192
|
+
# Invalid end-user.
|
193
|
+
nil
|
194
|
+
end
|
195
|
+
|
196
|
+
# Collect claim values of the end-user. Subclasses should override this
|
197
|
+
# method. This default implementation returns nil, meaning 'no claim values'.
|
198
|
+
#
|
199
|
+
# The argument of this method is an instance of
|
200
|
+
# <tt>Authlete::Model::Request::AuthenticationCallbackRequest</tt> and the subject
|
201
|
+
# which has been returned from the preceding call of <tt>authenticate_user</tt>
|
202
|
+
# method.
|
203
|
+
#
|
204
|
+
# 'Claim' is a piece of information about an end-user. A subclass should
|
205
|
+
# collect values of requested claims (<tt>req.claims</tt>) as many as
|
206
|
+
# possible and format them in JSON format like below.
|
207
|
+
#
|
208
|
+
# {
|
209
|
+
# "name": "Takahiko Kawasaki",
|
210
|
+
# "gender": "male"
|
211
|
+
# }
|
212
|
+
#
|
213
|
+
# Collected claim values are used to generate an {ID token}
|
214
|
+
# [http://openid.net/specs/openid-connect-core-1_0.html#IDToken].
|
215
|
+
#
|
216
|
+
# If no claim values are available, or if you don't want to provide any
|
217
|
+
# claim value, return nil.
|
218
|
+
def collect_claims(req, subject)
|
219
|
+
# No claim values.
|
220
|
+
nil
|
221
|
+
end
|
222
|
+
|
223
|
+
# Get the path of the authentication callback endpoint. This default
|
224
|
+
# implementation returns '/authentication'. Subclasses may override
|
225
|
+
# this method to change the path.
|
226
|
+
def authentication_callback_endpoint_path
|
227
|
+
'/authentication'
|
228
|
+
end
|
229
|
+
end
|
230
230
|
end
|