g5_authentication_client 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +39 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +351 -0
- data/Rakefile +14 -0
- data/g5_authentication_client.gemspec +34 -0
- data/lib/g5_authentication_client/client.rb +177 -0
- data/lib/g5_authentication_client/configuration.rb +138 -0
- data/lib/g5_authentication_client/token_info.rb +27 -0
- data/lib/g5_authentication_client/user.rb +32 -0
- data/lib/g5_authentication_client/version.rb +3 -0
- data/lib/g5_authentication_client.rb +11 -0
- data/spec/g5_authentication_client/client_spec.rb +335 -0
- data/spec/g5_authentication_client/configuration_spec.rb +210 -0
- data/spec/g5_authentication_client/token_info_spec.rb +36 -0
- data/spec/g5_authentication_client/user_spec.rb +92 -0
- data/spec/g5_authentication_client_spec.rb +11 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/module_configured_attribute.rb +37 -0
- data/spec/support/oauth_protected_resource.rb +81 -0
- metadata +252 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 97c68343930b548666879d796904ea3345cd791b
|
4
|
+
data.tar.gz: 9a41e522f8fd8ab0ded0d797ce29d2292b272dac
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8ff4eeaa114f7693c555bffc53a360a762897fb3f60e8dccee176eaf64c82af9d9e957e044f482826ecc33df5242a0692878c59a8b552a354c49bffed3c73290
|
7
|
+
data.tar.gz: 1d377a2678b5435e6f11f8003417cb5a25148fe0889f728d23a266160b09fbeb2dbd4356822a83f9531e3d949da9f5818afd39ef9e1887ae2a4b4c3c05ae8687
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
g5_authentication_client
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.0
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
## v0.2.0 (2014-03-10)
|
2
|
+
|
3
|
+
* First open source release to [RubyGems](http://rubygems.org/)
|
4
|
+
|
5
|
+
## v0.1.5 (2014-03-07)
|
6
|
+
|
7
|
+
* Add allow_password_credentials flag to determine whether client instances
|
8
|
+
* will allow use of username/passwored attributes
|
9
|
+
|
10
|
+
## v0.1.4 (2014-03-06)
|
11
|
+
|
12
|
+
* Change configure method namespace to g5_auth from g5_authentication_client
|
13
|
+
|
14
|
+
## v0.1.1 (2013-11-15)
|
15
|
+
|
16
|
+
* Add `G5AuthenticationClient::Client#sign_out_url`. The client should
|
17
|
+
redirect to this target URL in order sign out the current user.
|
18
|
+
|
19
|
+
## v0.1.0 (2013-11-05)
|
20
|
+
|
21
|
+
* Rename all references to `client_callback_url` to `redirect_uri`.
|
22
|
+
This is in order to maintain consistency with the terminology used
|
23
|
+
in the OAuth 2.0 spec. This is a breaking change for any code written
|
24
|
+
against earlier versions of the client.
|
25
|
+
|
26
|
+
## v0.0.3 (2013-09-23)
|
27
|
+
|
28
|
+
* Add support for retrieving user data based on current credentials
|
29
|
+
* Add `User#password_confirmation`
|
30
|
+
* Allow client to configure an OAuth access token directly (thereby
|
31
|
+
bypassing the OAuth authorization flow)
|
32
|
+
|
33
|
+
## v0.0.2 (2013-07-13)
|
34
|
+
|
35
|
+
* Update dependency on modelish to v0.3.x
|
36
|
+
|
37
|
+
## v0.0.1
|
38
|
+
|
39
|
+
* Initial release
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 G5
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,351 @@
|
|
1
|
+
# G5 Authentication Client #
|
2
|
+
|
3
|
+
A client library for the g5-authentication service.
|
4
|
+
|
5
|
+
## Current version ##
|
6
|
+
|
7
|
+
0.2.0
|
8
|
+
|
9
|
+
## Requirements ##
|
10
|
+
|
11
|
+
* Ruby >= 1.9.3
|
12
|
+
|
13
|
+
## Installation ##
|
14
|
+
|
15
|
+
In Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'g5_authentication_client'
|
19
|
+
```
|
20
|
+
|
21
|
+
Just rubygems:
|
22
|
+
|
23
|
+
```console
|
24
|
+
$ gem install g5_authentication_client
|
25
|
+
```
|
26
|
+
|
27
|
+
## Configuration ##
|
28
|
+
|
29
|
+
### Environment variables ###
|
30
|
+
|
31
|
+
You can set the default value for several configuration settings via
|
32
|
+
environment variable (not all of these will be used concurrently!):
|
33
|
+
|
34
|
+
* `G5_AUTH_CLIENT_ID` - the OAuth 2.0 application ID from the auth server
|
35
|
+
* `G5_AUTH_CLIENT_SECRET` - the OAuth 2.0 application secret from the auth server
|
36
|
+
* `G5_AUTH_REDIRECT_URI` - the OAuth 2.0 redirect URI registered with the auth server
|
37
|
+
* `G5_AUTH_ENDPOINT` - the endpoint URL for the G5 auth server
|
38
|
+
* `G5_AUTH_USERNAME` - the username for the end user to authenticate as
|
39
|
+
* `G5_AUTH_PASSWORD` - the password for the end user to authenticate as
|
40
|
+
* `G5_AUTH_ACCESS_TOKEN` - a valid OAuth 2.0 access token (note that tokens do expire)
|
41
|
+
|
42
|
+
### Module-level config ###
|
43
|
+
|
44
|
+
Any settings that are configured on the `G5AuthenticationClient` module will
|
45
|
+
apply to all instances of `G5AuthenticationClient::Client`, unless that setting
|
46
|
+
is overridden at the client level.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
G5AuthenticationClient.configure do |config|
|
50
|
+
config.client_id = 'blah'
|
51
|
+
config.client_secret = 'blah'
|
52
|
+
config.redirect_uri = 'blah'
|
53
|
+
config.endpoint = 'blah'
|
54
|
+
config.debug = true
|
55
|
+
config.logger = Rails.logger
|
56
|
+
|
57
|
+
# It would be unusual to configure non-client credentials at the module
|
58
|
+
# level, but it is possible. You would only need to configure one of the
|
59
|
+
# following:
|
60
|
+
|
61
|
+
# If you already have an OAuth access token
|
62
|
+
config.access_token = 'blah'
|
63
|
+
|
64
|
+
# For the OAuth authorization code grant type
|
65
|
+
config.authorization_code = 'blah'
|
66
|
+
|
67
|
+
# For the resource owner password credentials grant type
|
68
|
+
config.username = 'blah'
|
69
|
+
config.password = 'blah'
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
### Client-level config ###
|
74
|
+
|
75
|
+
To override a setting for a particular instance of `G5AuthenticationClient::Client`
|
76
|
+
without affecting any other instances, you can pass the configuration option
|
77
|
+
into the initializer:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
G5AuthenticationClient.configure do |config|
|
81
|
+
config.endpoint = 'https://dev-auth.g5search.com'
|
82
|
+
end
|
83
|
+
|
84
|
+
client = G5AuthenticationClient::Client.new(endpoint: 'http://localhost:3000')
|
85
|
+
client.endpoint
|
86
|
+
# => "http://localhost:3000"
|
87
|
+
|
88
|
+
client = G5AuthenticationClient::Client.new
|
89
|
+
client.endpoint
|
90
|
+
# => "https://dev-auth.g5search.com"
|
91
|
+
```
|
92
|
+
|
93
|
+
## Usage ##
|
94
|
+
|
95
|
+
### Retrieving user information ###
|
96
|
+
|
97
|
+
Assuming you have a valid access token, set up your client instance:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
auth_client = G5AuthenticationClient::Client.new(access_token: 'my_token')
|
101
|
+
```
|
102
|
+
|
103
|
+
You can retrieve information for the user associated with the access token:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
current_user = auth_client.me
|
107
|
+
# => #<G5AuthenticationClient::User email="my.user@test.host" id=1>
|
108
|
+
```
|
109
|
+
|
110
|
+
You can also retrieve informatino about any other user by ID:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
user = auth_client.get_user(42)
|
114
|
+
# => #<G5AuthenticationClient::User email="another.user@test.host" id=42>
|
115
|
+
```
|
116
|
+
|
117
|
+
### Retrieving token information ###
|
118
|
+
|
119
|
+
You can retrieve information specific to the current access token, including
|
120
|
+
scopes and expiration time:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
auth_client = G5AuthenticationClient::Client.new(access_token: 'my_access_token')
|
124
|
+
token_info = auth_client.token_info
|
125
|
+
# => #<G5AuthenticationClient::TokenInfo application_uid={"uid"=>"my_application_id"} expires_in_seconds=5183805 resource_owner_id=1 scopes=[]>
|
126
|
+
```
|
127
|
+
|
128
|
+
To retrieve the token value itself:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
auth_client.get_access_token
|
132
|
+
# => "my_access_token"
|
133
|
+
```
|
134
|
+
|
135
|
+
### Creating a user ###
|
136
|
+
|
137
|
+
To create a user, you need their email and password. You can either pass in
|
138
|
+
these credentials as an option hash:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
auth_client = G5AuthenticationClient::Client.new(access_token: 'my_access_token')
|
142
|
+
user = auth_client.create_user(email: 'new.user@test.host',
|
143
|
+
password: 'testing',
|
144
|
+
password_confirmation: 'testing')
|
145
|
+
# => #<G5AuthenticationClient::User email="new.user@test.host" id=123>
|
146
|
+
```
|
147
|
+
|
148
|
+
Or you can pass in an instance of `G5AuthenticationClient::User`:
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
user = G5AuthenticationClient::User.new(email: 'new.user@test.host',
|
152
|
+
password: 'testing',
|
153
|
+
password_confirmation: 'testing')
|
154
|
+
auth_client.create_user(user)
|
155
|
+
```
|
156
|
+
|
157
|
+
### Updating a user ###
|
158
|
+
|
159
|
+
To update an existing user, you'll need the user ID and the new credentials:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
auth_client = G5AuthenticationClient::Client.new(access_token: 'my_access_token')
|
163
|
+
auth_client.update_user(id: 42,
|
164
|
+
email: 'updated.email@test.host',
|
165
|
+
password: 'updated_secret',
|
166
|
+
password_confirmation: 'updated_secret')
|
167
|
+
```
|
168
|
+
|
169
|
+
You can also pass in a `G5AuthenticationClient::User` instance instead:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
user = auth_client.create_user(email: 'new.user@test.host',
|
173
|
+
password: 'secret',
|
174
|
+
password_confirmation: 'secret')
|
175
|
+
user.email = 'updated.email@test.host'
|
176
|
+
auth_client.update_user(user)
|
177
|
+
```
|
178
|
+
|
179
|
+
### Deleting a user ###
|
180
|
+
|
181
|
+
To delete a user, you need the user ID:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
auth_client = G5AuthenticationClient::Client.new(access_token: 'my_access_token')
|
185
|
+
auth_client.delete_user(42)
|
186
|
+
```
|
187
|
+
|
188
|
+
### Sign-out URL ###
|
189
|
+
|
190
|
+
In order to sign out of the G5 auth service from a web browser, your client
|
191
|
+
application must redirect to the auth server's sign-out URL. You can
|
192
|
+
pass in a redirect URL for the auth server to redirect back to after the
|
193
|
+
sign-out process is complete.
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
auth_client = G5AuthenticationClient::Client.new
|
197
|
+
auth_client.sign_out_url('https://myapp.host/callback')
|
198
|
+
# => "https://auth.g5search.com/users/sign_out?redirect_url=https%3A%2F%2Fmyapp.host%2Fcallback"
|
199
|
+
```
|
200
|
+
|
201
|
+
## Examples ##
|
202
|
+
|
203
|
+
These examples assume that you have already registered your client application
|
204
|
+
and at least one end user on the auth server.
|
205
|
+
|
206
|
+
### Authorization grant ####
|
207
|
+
|
208
|
+
You will need the following credentials:
|
209
|
+
|
210
|
+
* Client ID
|
211
|
+
* Client secret
|
212
|
+
* Redirect URI
|
213
|
+
* Authorization code
|
214
|
+
|
215
|
+
The client ID, client secret, and redirect URI will be the same for any request
|
216
|
+
your application may make, so you will probably want to configure these either
|
217
|
+
via environment variables or at the module level:
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
G5AuthenticationClient.configure do |config|
|
221
|
+
config.client_id = 'my-client-id'
|
222
|
+
config.client_secret = 'my-client-secret'
|
223
|
+
config.redirect_uri = 'https://test.host/callback'
|
224
|
+
end
|
225
|
+
```
|
226
|
+
|
227
|
+
Each authorization code can only be used once, so it's best configured on the
|
228
|
+
client instance:
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
auth_client = G5AuthenticationClient::Client.new(authorization_code: 'my_one_time_use_code')
|
232
|
+
```
|
233
|
+
|
234
|
+
You can now execute actions against the auth service using that client:
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
auth_client.me
|
238
|
+
# => #<G5AuthenticationClient::User email="another.user@test.host" id=42>
|
239
|
+
```
|
240
|
+
|
241
|
+
Or you can retrieve an access token in order to authenticate to another G5
|
242
|
+
service:
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
auth_client.get_access_token
|
246
|
+
# => "my-g5-access-token-value-abc123"
|
247
|
+
```
|
248
|
+
|
249
|
+
### Resource owner password credentials grant ###
|
250
|
+
|
251
|
+
This grant type is only available to highly trusted client applications that
|
252
|
+
do not require explicit authorization by the end user.
|
253
|
+
|
254
|
+
You will need the following credentials:
|
255
|
+
|
256
|
+
* Client ID
|
257
|
+
* Client secret
|
258
|
+
* Redirect URI
|
259
|
+
* Username
|
260
|
+
* Password
|
261
|
+
|
262
|
+
Your client credentials will always be the same for every request, so use
|
263
|
+
module-level configuration or environment variables for those:
|
264
|
+
|
265
|
+
```bash
|
266
|
+
export G5_AUTH_CLIENT_ID='my-client-id'
|
267
|
+
export G5_AUTH_CLIENT_SECRET='my-client-secret'
|
268
|
+
export G5_AUTH_REDIRECT_URI='https://test.host/callback'
|
269
|
+
```
|
270
|
+
|
271
|
+
If you want to use a different username and password per request, then you
|
272
|
+
should configure these on each client instance:
|
273
|
+
|
274
|
+
```ruby
|
275
|
+
auth_client = G5AuthenticationClient::Client.new(username: 'user1@test.host', password: 'secret1')
|
276
|
+
auth_client.me
|
277
|
+
# => #<G5AuthenticationClient::User email="user1@test.host" id=1>
|
278
|
+
|
279
|
+
auth_client = G5AuthenticationClient::Client.new(username: 'user2@test.host', password: 'secret2')
|
280
|
+
auth_client.me
|
281
|
+
# => #<G5AuthenticationClient::User email="user2@test.host" id=2>
|
282
|
+
```
|
283
|
+
|
284
|
+
However, if you want to use the same user credentials for all requests,
|
285
|
+
you can set them using environment variables:
|
286
|
+
|
287
|
+
```bash
|
288
|
+
export G5_AUTH_USERNAME='user1@test.host'
|
289
|
+
export G5_AUTH_PASSWORD='secret1'
|
290
|
+
```
|
291
|
+
|
292
|
+
Now every client instance will authenticate as the same user by default:
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
G5AuthenticationClient::Client.new.me
|
296
|
+
# => #<G5AuthenticationClient::User email="user1@test.host" id=1>
|
297
|
+
|
298
|
+
G5AuthenticationClient::Client.new.me
|
299
|
+
# => #<G5AuthenticationClient::User email="user1@test.host" id=1>
|
300
|
+
```
|
301
|
+
|
302
|
+
## Authors ##
|
303
|
+
|
304
|
+
* Rob Revels / [@sleverbor](https://github.com/sleverbor)
|
305
|
+
* Maeve Revels / [@maeve](https://github.com/maeve)
|
306
|
+
|
307
|
+
## Contributing ##
|
308
|
+
|
309
|
+
1. Fork it
|
310
|
+
2. Get it running
|
311
|
+
3. Create your feature branch (`git checkout -b my-new-feature`)
|
312
|
+
4. Write your code and **specs**
|
313
|
+
5. Commit your changes (`git commit -am 'Add some feature'`)
|
314
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
315
|
+
7. Create new Pull Request
|
316
|
+
|
317
|
+
If you find bugs, have feature requests or questions, please
|
318
|
+
[file an issue](https://github.com/G5/g5_authentication_client/issues).
|
319
|
+
|
320
|
+
### Running the specs ###
|
321
|
+
|
322
|
+
All you have to do is execute rspec through bundler:
|
323
|
+
|
324
|
+
```console
|
325
|
+
$ bundle exec rspec spec
|
326
|
+
```
|
327
|
+
|
328
|
+
## License ##
|
329
|
+
|
330
|
+
Copyright (c) 2014 G5
|
331
|
+
|
332
|
+
MIT License
|
333
|
+
|
334
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
335
|
+
a copy of this software and associated documentation files (the
|
336
|
+
"Software"), to deal in the Software without restriction, including
|
337
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
338
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
339
|
+
permit persons to whom the Software is furnished to do so, subject to
|
340
|
+
the following conditions:
|
341
|
+
|
342
|
+
The above copyright notice and this permission notice shall be
|
343
|
+
included in all copies or substantial portions of the Software.
|
344
|
+
|
345
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
346
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
347
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
348
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
349
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
350
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
351
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
namespace :doc do
|
9
|
+
require 'yard'
|
10
|
+
YARD::Rake::YardocTask.new do |task|
|
11
|
+
task.files = ['README.md', 'lib/**/*.rb']
|
12
|
+
task.options = ['--markup', 'markdown']
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "g5_authentication_client/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "g5_authentication_client"
|
6
|
+
s.version = G5AuthenticationClient::VERSION
|
7
|
+
s.authors = ["Rob Revels", "Maeve Revels"]
|
8
|
+
s.email = ["rob.revels@getg5.com", "maeve.revels@getg5.com"]
|
9
|
+
s.homepage = "https://github.com/G5/g5_authentication_client"
|
10
|
+
s.summary = "Client for the G5 Auth service"
|
11
|
+
s.description = "Client for the G5 Auth service"
|
12
|
+
|
13
|
+
s.rubyforge_project = "g5_authentication_client"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_dependency('modelish', '~> 0.3')
|
21
|
+
s.add_dependency('configlet', '~> 2.1')
|
22
|
+
s.add_dependency('oauth2')
|
23
|
+
s.add_dependency('addressable')
|
24
|
+
|
25
|
+
s.add_development_dependency('rake')
|
26
|
+
s.add_development_dependency('rspec')
|
27
|
+
s.add_development_dependency('webmock')
|
28
|
+
s.add_development_dependency('fakefs')
|
29
|
+
s.add_development_dependency('simplecov')
|
30
|
+
s.add_development_dependency('codeclimate-test-reporter')
|
31
|
+
s.add_development_dependency('yard')
|
32
|
+
s.add_development_dependency('rdiscount')
|
33
|
+
s.add_development_dependency('vcr')
|
34
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
|
3
|
+
module G5AuthenticationClient
|
4
|
+
# G5AuthenticationClient::Client can be used to authenticate with the G5 OAuth 2
|
5
|
+
# authorization server. It can also be used to create G5 users.
|
6
|
+
class Client
|
7
|
+
# Mutators for configuration options
|
8
|
+
attr_writer *G5AuthenticationClient::VALID_CONFIG_OPTIONS
|
9
|
+
# Accessors for configuration options
|
10
|
+
G5AuthenticationClient::VALID_CONFIG_OPTIONS.each do |opt|
|
11
|
+
define_method(opt) { get_value(opt) }
|
12
|
+
end
|
13
|
+
|
14
|
+
# @!attribute [rw] allow_password_credentials
|
15
|
+
# @return [String] 'true' if the client is using the
|
16
|
+
# username and password attributes
|
17
|
+
|
18
|
+
# @!attribute [rw] endpoint
|
19
|
+
# @return [String] the g5-authentication service endpoint URL
|
20
|
+
|
21
|
+
# @!attribute [rw] username
|
22
|
+
# @return [String] the username for authentication
|
23
|
+
|
24
|
+
# @!attribute [rw] password
|
25
|
+
# @return [String] the password for authentication
|
26
|
+
|
27
|
+
# @!attribute [rw] debug
|
28
|
+
# @return [String] 'true' if debug logging is enabled
|
29
|
+
|
30
|
+
# @!attribute [rw] logger
|
31
|
+
# @return [Logger] custom logger instance
|
32
|
+
|
33
|
+
# @!attribute [rw] client_id
|
34
|
+
# @return [String] client id for this application
|
35
|
+
|
36
|
+
# @!attribute [rw] client_secret
|
37
|
+
# @return [String] client secret for this application
|
38
|
+
|
39
|
+
# @!attribute [rw] redirect_uri
|
40
|
+
# @return [String] callback url for application
|
41
|
+
|
42
|
+
# @!attribute [rw] authorization_code
|
43
|
+
# @return [String] code provided by authorization server
|
44
|
+
|
45
|
+
# @!attribute [rw] access_token
|
46
|
+
# @return [String] access token value provided by authorization server
|
47
|
+
|
48
|
+
def debug?
|
49
|
+
self.debug.to_s == 'true'
|
50
|
+
end
|
51
|
+
|
52
|
+
# Initializes the client.
|
53
|
+
#
|
54
|
+
# @param [Hash] options
|
55
|
+
# @option options [true,false] :debug true enabled debug logging (defaults to false)
|
56
|
+
# @option options [Logger] :logger a custom logger instance (defaults to STDOUT)
|
57
|
+
# @option options [String] :username The username for authenticating
|
58
|
+
# @option options [String] :password The password for authenticating
|
59
|
+
# @option options [String] :endpoint The authentication endpoint
|
60
|
+
# @option options [String] :client_id The client id for this application
|
61
|
+
# @option options [String] :client_secret The client secret for this application
|
62
|
+
# @option options [String] :redirect_uri The client callback url for this application.
|
63
|
+
# @option options [String] :authorization_code The authentication code from the authorization server.
|
64
|
+
# @option options [String] :allow_password_credentials The client will use username and password if true.
|
65
|
+
def initialize(options={})
|
66
|
+
options.each { |k,v| self.send("#{k}=", v) if self.respond_to?("#{k}=") }
|
67
|
+
end
|
68
|
+
|
69
|
+
# Tells whether a client instance will use the username/password credentials
|
70
|
+
# @return [Boolean] whether the client will use username/password
|
71
|
+
def allow_password_credentials?
|
72
|
+
allow_password_credentials=='true' && !username.nil? && !password.nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
# Retrieves the access token as a string
|
76
|
+
# @return [String] the access token value
|
77
|
+
def get_access_token
|
78
|
+
oauth_access_token.token
|
79
|
+
end
|
80
|
+
|
81
|
+
# Retrieves an attribute's value. If the attribute has not been set
|
82
|
+
# on this object, it is retrieved from the global configuration.
|
83
|
+
#
|
84
|
+
# @see G5AuthenticationClient.configure
|
85
|
+
#
|
86
|
+
# @param [Symbol] attribute the name of the attribute
|
87
|
+
# @return [String] the value of the attribute
|
88
|
+
def get_value(attribute)
|
89
|
+
instance_variable_get("@#{attribute}") || G5AuthenticationClient.send(attribute)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Create a user from the options
|
93
|
+
# @param [Hash] options
|
94
|
+
# @option options [String] :email The new user's email address
|
95
|
+
# @option options [String] :password The new user's password
|
96
|
+
# @option options [String] :password_confirmation The new user's password confirmation string
|
97
|
+
# @return [G5AuthenticationClient::User]
|
98
|
+
def create_user(options={})
|
99
|
+
user=User.new(options)
|
100
|
+
user.validate_for_create!
|
101
|
+
response=oauth_access_token.post('/v1/users', params: {user: user.to_hash})
|
102
|
+
User.new(response.parsed)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Update an existing user
|
106
|
+
# @param [Hash] options
|
107
|
+
# @option options [String] :email The new user's email address
|
108
|
+
# @option options [String] :password The new user's password
|
109
|
+
# @option options [String] :password_confirmation The new user's password confirmation string
|
110
|
+
# @return [G5AuthenticationClient::User]
|
111
|
+
def update_user(options={})
|
112
|
+
user=User.new(options)
|
113
|
+
user.validate!
|
114
|
+
response=oauth_access_token.put("/v1/users/#{user.id}", params: {user: user.to_hash})
|
115
|
+
User.new(response.parsed)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Get a user
|
119
|
+
# @param [Integer] id the user ID in the remote service
|
120
|
+
# @return [G5AuthenticationClient::User]
|
121
|
+
def get_user(id)
|
122
|
+
response=oauth_access_token.get("/v1/users/#{id}")
|
123
|
+
User.new(response.parsed)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Delete a user
|
127
|
+
# @param [Integer] id the user ID in the remote service
|
128
|
+
# @return [G5AuthenticationClient::User]
|
129
|
+
def delete_user(id)
|
130
|
+
response=oauth_access_token.delete("/v1/users/#{id}")
|
131
|
+
User.new(response.parsed)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Get the current user based on configured credentials
|
135
|
+
# @return [G5AuthenticationClient::User]
|
136
|
+
def me
|
137
|
+
response = oauth_access_token.get('/v1/me')
|
138
|
+
User.new(response.parsed)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Get the access token info for the currently active token
|
142
|
+
# @return [G5AuthenticationClient::TokenInfo]
|
143
|
+
def token_info
|
144
|
+
response = oauth_access_token.get('/oauth/token/info')
|
145
|
+
TokenInfo.new(response.parsed)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Return the URL for signing out of the auth server.
|
149
|
+
# Clients should redirect to this URL to globally sign out.
|
150
|
+
#
|
151
|
+
# @param [String] redirect_url the URL that the auth server should redirect back to after sign out
|
152
|
+
# @return [String] the auth server endpoint for signing out
|
153
|
+
def sign_out_url(redirect_url=nil)
|
154
|
+
auth_server_url = Addressable::URI.parse(endpoint)
|
155
|
+
auth_server_url.path = '/users/sign_out'
|
156
|
+
auth_server_url.query_values = {redirect_url: redirect_url} if redirect_url
|
157
|
+
auth_server_url.to_s
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
def oauth_client
|
162
|
+
OAuth2::Client.new(client_id, client_secret, site: endpoint)
|
163
|
+
end
|
164
|
+
|
165
|
+
def oauth_access_token
|
166
|
+
@oauth_access_token ||= if access_token
|
167
|
+
OAuth2::AccessToken.new(oauth_client, access_token)
|
168
|
+
elsif authorization_code
|
169
|
+
oauth_client.auth_code.get_token(authorization_code, redirect_uri: redirect_uri)
|
170
|
+
elsif allow_password_credentials?
|
171
|
+
oauth_client.password.get_token(username,password)
|
172
|
+
else
|
173
|
+
raise "Insufficient credentials for access token. Supply a username/password or authentication code"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|