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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b18c3acf2bff70c5782f1dfa6e3d3a652ad60759
4
- data.tar.gz: b684b91b3dbc5a9b6c7adf12094f730c4e8d2790
2
+ SHA256:
3
+ metadata.gz: 76874c7e1a1d4c0ce39569f657df73d1d445df1907bfa08602eb75fae353ce79
4
+ data.tar.gz: 7ce55dd3873f5b4a79f2df58ce84da52d0c45889701820e5a711fd1d12c496ac
5
5
  SHA512:
6
- metadata.gz: a12c3ea20cc4e6a487f4509c6fcfc82805e54b2fbcaf0861e7378f2dec11f5549050edf505a9aae0b341ee122981034019ad79d580018258bdda5838d3d14d72
7
- data.tar.gz: 450b964300dad2371ffcf3def464eed3014662c82c78dc1f321a1fecce7f1918cb341e2bfe68e77ca0f7f0d44947b8a464136a5caec395e55fccfa15b878ed6c
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