g5_authenticatable_api 0.2.0
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 +7 -0
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile +38 -0
- data/LICENSE.txt +22 -0
- data/README.md +286 -0
- data/Rakefile +1 -0
- data/circle.yml +4 -0
- data/g5_authenticatable_api.gemspec +23 -0
- data/lib/g5_authenticatable_api/helpers/grape.rb +27 -0
- data/lib/g5_authenticatable_api/helpers/rails.rb +26 -0
- data/lib/g5_authenticatable_api/railtie.rb +11 -0
- data/lib/g5_authenticatable_api/token_validator.rb +65 -0
- data/lib/g5_authenticatable_api/version.rb +3 -0
- data/lib/g5_authenticatable_api.rb +9 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/api/hello_api.rb +13 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +16 -0
- data/spec/dummy/app/assets/javascripts/articles.js +2 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/assets/stylesheets/articles.css +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/controllers/rails_api/articles_controller.rb +11 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/articles_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/article.rb +2 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/user.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +30 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml.ci +6 -0
- data/spec/dummy/config/database.yml.sample +50 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/devise.rb +254 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/devise.en.yml +59 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +63 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20140217124048_devise_create_users.rb +15 -0
- data/spec/dummy/db/migrate/20140223194521_create_articles.rb +11 -0
- data/spec/dummy/db/schema.rb +39 -0
- data/spec/dummy/db/seeds.rb +7 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/lib/tasks/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/robots.txt +5 -0
- data/spec/dummy/vendor/assets/javascripts/.keep +0 -0
- data/spec/dummy/vendor/assets/stylesheets/.keep +0 -0
- data/spec/factories/user.rb +8 -0
- data/spec/lib/g5_authenticatable_api/token_validator_spec.rb +199 -0
- data/spec/lib/g5_authenticatable_api/version_spec.rb +7 -0
- data/spec/requests/grape_api_spec.rb +21 -0
- data/spec/requests/rails_api_spec.rb +13 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/support/factory_girl.rb +5 -0
- data/spec/support/shared_contexts/invalid_access_token.rb +24 -0
- data/spec/support/shared_contexts/valid_access_token.rb +7 -0
- data/spec/support/shared_examples/token_authenticatable_api.rb +106 -0
- data/spec/support/shared_examples/warden_authenticatable_api.rb +31 -0
- data/spec/support/warden.rb +4 -0
- metadata +223 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cd9ed6f231034a1d906d81e1fc66b0787fc7596e
|
4
|
+
data.tar.gz: bed5680f12d4d43a28b7aff5f2b55773ce8d7dd5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f77007e0fdeb669211365aa53a19bc011ab73c1297b9a6ae23155f7cc3a798f944517cbe1e72746c50cc430be45fecb9a6a2575e2e60981d816d30bbc6ac69a6
|
7
|
+
data.tar.gz: 8f425de57b86817df5528822b914030892292b622c9af9382a946270d66c91752de9188bb57884e70aba10909cef315da293acf3b00d38fdd75d69246931aa01
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
.DS_Store
|
2
|
+
*.gem
|
3
|
+
*.rbc
|
4
|
+
.bundle
|
5
|
+
.config
|
6
|
+
.yardoc
|
7
|
+
Gemfile.lock
|
8
|
+
InstalledFiles
|
9
|
+
_yardoc
|
10
|
+
coverage
|
11
|
+
doc/
|
12
|
+
lib/bundler/man
|
13
|
+
pkg
|
14
|
+
rdoc
|
15
|
+
spec/reports
|
16
|
+
test/tmp
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
.env.*
|
20
|
+
spec/dummy/db/*.sqlite3
|
21
|
+
spec/dummy/log/*.log
|
22
|
+
spec/dummy/tmp/
|
23
|
+
spec/dummy/.sass-cache
|
24
|
+
spec/dummy/config/database.yml
|
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
## v0.2.0 (2014-03-12)
|
2
|
+
|
3
|
+
* First open source release to [RubyGems](https://rubygems.org)
|
4
|
+
|
5
|
+
## v0.1.1 (2014-03-07)
|
6
|
+
|
7
|
+
* Bug fix: ignore any configured resource owner password credentials during
|
8
|
+
token validation.
|
9
|
+
|
10
|
+
## v0.1.0 (2014-02-26)
|
11
|
+
|
12
|
+
* Implement Rails API helpers
|
13
|
+
* Renamed `G5AuthenticatableApi::GrapeHelpers` to
|
14
|
+
`G5AuthenticatableApi::Helpers::Grape`
|
15
|
+
|
16
|
+
## v0.0.1 (2014-02-20)
|
17
|
+
|
18
|
+
* Initial release with Grape API helpers
|
data/Gemfile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Declare your gem's dependencies in g5_authenticatable_api.gemspec.
|
4
|
+
# Bundler will treat runtime dependencies like base dependencies, and
|
5
|
+
# development dependencies will be added by default to the :development group.
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
# Gems used by the dummy application
|
9
|
+
gem 'rails', '~> 4.0.2'
|
10
|
+
gem 'jquery-rails'
|
11
|
+
gem 'pg'
|
12
|
+
gem 'grape'
|
13
|
+
gem 'devise'
|
14
|
+
gem 'devise_g5_authenticatable'
|
15
|
+
|
16
|
+
group :test, :development do
|
17
|
+
gem 'rspec-rails', '~> 2.14'
|
18
|
+
gem 'pry'
|
19
|
+
end
|
20
|
+
|
21
|
+
group :test do
|
22
|
+
gem 'capybara'
|
23
|
+
gem 'factory_girl_rails', '~> 4.3', require: false
|
24
|
+
gem 'simplecov', require: false
|
25
|
+
gem 'codeclimate-test-reporter', require: false
|
26
|
+
gem 'webmock'
|
27
|
+
gem 'shoulda-matchers'
|
28
|
+
gem 'rspec-http', require: false
|
29
|
+
end
|
30
|
+
|
31
|
+
# Declare any dependencies that are still in development here instead of in
|
32
|
+
# your gemspec. These might include edge Rails or gems from your path or
|
33
|
+
# Git. Remember to move these dependencies to your gemspec before releasing
|
34
|
+
# your gem to rubygems.org.
|
35
|
+
# gem 'g5_authentication_client', git: 'git@github.com:G5/g5_authentication_client.git', branch: 'master'
|
36
|
+
|
37
|
+
# To use debugger
|
38
|
+
# gem 'debugger'
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 maeve
|
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,286 @@
|
|
1
|
+
# G5 Authenticatable API
|
2
|
+
|
3
|
+
A set of helpers for securing Rails or Grape APIs using G5 Auth.
|
4
|
+
|
5
|
+
The helpers can be used in conjunction with
|
6
|
+
[devise_g5_authenticatable](https://github.com/G5/devise_g5_authenticatable)
|
7
|
+
to protect an API for a website, or they may be used to protect a stand-alone
|
8
|
+
service using token-based authentication.
|
9
|
+
|
10
|
+
## Current Version
|
11
|
+
|
12
|
+
0.2.0
|
13
|
+
|
14
|
+
## Requirements
|
15
|
+
|
16
|
+
* [rails](http://rubyonrails.org/) >= 3.2
|
17
|
+
|
18
|
+
**OR**
|
19
|
+
|
20
|
+
* [grape](https://github.com/intridea/grape)
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
1. Add this line to your application's Gemfile:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
gem 'g5_authenticatable_api'
|
28
|
+
```
|
29
|
+
|
30
|
+
2. And then execute:
|
31
|
+
|
32
|
+
```console
|
33
|
+
bundle
|
34
|
+
```
|
35
|
+
|
36
|
+
## Configuration
|
37
|
+
|
38
|
+
The API helpers need to know the endpoint for the G5 auth server to use when
|
39
|
+
validating tokens. This may be configured in one of several ways:
|
40
|
+
|
41
|
+
* Set the `G5_AUTH_ENDPOINT` environment variable (typically to either
|
42
|
+
https://dev-auth.g5search.com or https://auth.g5search.com).
|
43
|
+
|
44
|
+
**OR**
|
45
|
+
|
46
|
+
* Configure the `G5AuthenticationClient` module directly, perhaps in an
|
47
|
+
initializer:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
G5AuthenticationClient.configure do |config|
|
51
|
+
config.endpoint = 'https://dev-auth.g5search.com'
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
## Usage
|
56
|
+
|
57
|
+
### Rails
|
58
|
+
|
59
|
+
To require authentication for all API actions:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
class MyResourceController < ApplicationController
|
63
|
+
before_filter :authenticate_api_user!
|
64
|
+
|
65
|
+
respond_to :json
|
66
|
+
|
67
|
+
# ...
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
To require authentication for some API actions:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
class MyResourceController < ApplicationController
|
75
|
+
before_filter :authenticate_api_user!, only: [:create, :update]
|
76
|
+
|
77
|
+
respond_to :json
|
78
|
+
|
79
|
+
# ...
|
80
|
+
end
|
81
|
+
```
|
82
|
+
|
83
|
+
### Grape
|
84
|
+
|
85
|
+
To require authentication for all endpoints exposed by your API:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
class MyApi < Grape::API
|
89
|
+
helpers G5AuthenticatableApi::Helpers::Grape
|
90
|
+
|
91
|
+
before { authenticate_user! }
|
92
|
+
|
93
|
+
# ...
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
To selectively require authentication for some endpoints but not
|
98
|
+
others:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
class MyApi < Grape::API
|
102
|
+
helpers G5AuthenticatableApi::Helpers::Grape
|
103
|
+
|
104
|
+
get :secure do
|
105
|
+
authenticate_user!
|
106
|
+
{ secure: 'data' }
|
107
|
+
end
|
108
|
+
|
109
|
+
get :open do
|
110
|
+
{ hello: 'world' }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
### Submitting a token
|
116
|
+
|
117
|
+
Authenticated requests follow the requirements described by
|
118
|
+
[OAuth 2.0 Bearer Token specification](http://tools.ietf.org/html/rfc6750#section-2).
|
119
|
+
If you are relying on token-based authentication for your API, there are three
|
120
|
+
ways that an OAuth access token may be submitted as part of a request:
|
121
|
+
|
122
|
+
* In the `Authorization` HTTP header, with the format "Bearer \<access_token\>"
|
123
|
+
|
124
|
+
```http
|
125
|
+
GET /resource HTTP/1.1
|
126
|
+
Host: server.example.com
|
127
|
+
Authorization: Bearer mF_9.B5f-4.1JqM
|
128
|
+
```
|
129
|
+
|
130
|
+
* As the value of the `access_token` form-encoded body parameter:
|
131
|
+
|
132
|
+
```http
|
133
|
+
POST /resource HTTP/1.1
|
134
|
+
Host: server.example.com
|
135
|
+
Content-Type: application/x-www-form-urlencoded
|
136
|
+
|
137
|
+
access_token=mF_9.B5f-4.1JqM
|
138
|
+
```
|
139
|
+
|
140
|
+
* As the value of the `access_token` query URI parameter:
|
141
|
+
|
142
|
+
```http
|
143
|
+
GET /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1
|
144
|
+
Host: server.example.com
|
145
|
+
```
|
146
|
+
|
147
|
+
### Unauthorized response
|
148
|
+
|
149
|
+
If there is no logged in user and token authentication fails, secure API methods
|
150
|
+
will return a response with an HTTP status of 401. More detailed information will
|
151
|
+
be available in the `WWW-Authenticate` response header, as described in the
|
152
|
+
[OAuth 2.0 Bearer Token specification](http://tools.ietf.org/html/rfc6750#section-3).
|
153
|
+
|
154
|
+
In brief, `WWW-Authenticate` header will contain one of the following error codes
|
155
|
+
when token validation fails against G5 Auth:
|
156
|
+
|
157
|
+
* `invalid_request` (the default)
|
158
|
+
* `invalid_token`
|
159
|
+
* `insufficent_scope`
|
160
|
+
|
161
|
+
The header may also have an error description if one is available. For
|
162
|
+
example:
|
163
|
+
|
164
|
+
```http
|
165
|
+
HTTP/1.1 401 Unauthorized
|
166
|
+
WWW-Authenticate: Bearer realm="example",
|
167
|
+
error="invalid_token",
|
168
|
+
error_description="The access token expired"
|
169
|
+
```
|
170
|
+
|
171
|
+
## Examples
|
172
|
+
|
173
|
+
### Securing an Ember application backed by a Grape API
|
174
|
+
|
175
|
+
Use devise to protect the controller action that serves your ember
|
176
|
+
application:
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
class WelcomeController < ApplicationController
|
180
|
+
before_filter :authenticate_user!
|
181
|
+
|
182
|
+
def index
|
183
|
+
end
|
184
|
+
end
|
185
|
+
```
|
186
|
+
|
187
|
+
Then protect the API that ember talks to:
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
class MyApi < Grape::API
|
191
|
+
helpers G5AuthenticatableApi::Helpers::Grape
|
192
|
+
|
193
|
+
before { authenticate_user! }
|
194
|
+
|
195
|
+
# Your API endpoints ...
|
196
|
+
end
|
197
|
+
```
|
198
|
+
|
199
|
+
That's it! No client-side changes are necessary.
|
200
|
+
|
201
|
+
### Token-based authentication for a Rails API
|
202
|
+
|
203
|
+
Protect your API actions in your controller:
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
class Api::MyResourcesController < ApplicationController
|
207
|
+
before_filter :authenticate_api_user!
|
208
|
+
|
209
|
+
respond_to :json
|
210
|
+
|
211
|
+
def show
|
212
|
+
# ...
|
213
|
+
end
|
214
|
+
end
|
215
|
+
```
|
216
|
+
|
217
|
+
To include the token in the authorization header:
|
218
|
+
|
219
|
+
```console
|
220
|
+
curl --header "Authorization: Bearer this-is-where-my-token-goes" https://myhost/api/my_resources/42
|
221
|
+
```
|
222
|
+
|
223
|
+
To include the token as a param:
|
224
|
+
|
225
|
+
```console
|
226
|
+
curl https://myhost/api/my_resources/42?access_token=this-is-where-my-token-goes
|
227
|
+
```
|
228
|
+
|
229
|
+
## Authors
|
230
|
+
|
231
|
+
* Maeve Revels / [@maeve](https://github.com/maeve)
|
232
|
+
* Rob Revels / [@sleverbor](https://github.com/sleverbor)
|
233
|
+
|
234
|
+
## Contributing
|
235
|
+
|
236
|
+
1. [Fork it](https://github.com/G5/g5_authenticatable_api/fork)
|
237
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
238
|
+
3. Write your code and **specs**
|
239
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
240
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
241
|
+
6. Create a new Pull Request
|
242
|
+
|
243
|
+
If you find bugs, have feature requests or questions, please
|
244
|
+
[file an issue](https://github.com/G5/g5_authenticatable_api/issues).
|
245
|
+
|
246
|
+
### Specs
|
247
|
+
|
248
|
+
Before running the specs for the first time, you will need to initialize the
|
249
|
+
database for the test Rails application.
|
250
|
+
|
251
|
+
```console
|
252
|
+
$ cp spec/dummy/config/database.yml.sample spec/dummy/config/database.yml
|
253
|
+
$ (cd spec/dummy; RAILS_ENV=test bundle exec rake db:setup)
|
254
|
+
```
|
255
|
+
|
256
|
+
To execute the entire test suite:
|
257
|
+
|
258
|
+
```console
|
259
|
+
$ bundle exec rspec spec
|
260
|
+
```
|
261
|
+
|
262
|
+
## License
|
263
|
+
|
264
|
+
Copyright (c) 2014 G5
|
265
|
+
|
266
|
+
MIT License
|
267
|
+
|
268
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
269
|
+
a copy of this software and associated documentation files (the
|
270
|
+
"Software"), to deal in the Software without restriction, including
|
271
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
272
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
273
|
+
permit persons to whom the Software is furnished to do so, subject to
|
274
|
+
the following conditions:
|
275
|
+
|
276
|
+
The above copyright notice and this permission notice shall be
|
277
|
+
included in all copies or substantial portions of the Software.
|
278
|
+
|
279
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
280
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
281
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
282
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
283
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
284
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
285
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
286
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/circle.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'g5_authenticatable_api/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'g5_authenticatable_api'
|
8
|
+
spec.version = G5AuthenticatableApi::VERSION
|
9
|
+
spec.authors = ['Maeve Revels']
|
10
|
+
spec.email = ['maeve.revels@getg5.com']
|
11
|
+
spec.summary = 'Helpers for securing APIs with G5'
|
12
|
+
spec.description = 'Helpers for securing APIs with G5'
|
13
|
+
spec.homepage = 'https://github.com/G5/g5_authenticatable_api'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'rack'
|
22
|
+
spec.add_dependency 'g5_authentication_client', '~> 0.2'
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'g5_authenticatable_api/token_validator'
|
2
|
+
|
3
|
+
module G5AuthenticatableApi
|
4
|
+
module Helpers
|
5
|
+
module Grape
|
6
|
+
def authenticate_user!
|
7
|
+
raise_auth_error if !(warden.try(:authenticated?) || token_validator.valid?)
|
8
|
+
end
|
9
|
+
|
10
|
+
def warden
|
11
|
+
env['warden']
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def token_validator
|
16
|
+
request = Rack::Request.new(env)
|
17
|
+
@token_validator ||= TokenValidator.new(request.params, headers)
|
18
|
+
end
|
19
|
+
|
20
|
+
def raise_auth_error
|
21
|
+
throw :error, message: 'Unauthorized',
|
22
|
+
status: 401,
|
23
|
+
headers: {'WWW-Authenticate' => token_validator.auth_response_header}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'g5_authenticatable_api/token_validator'
|
2
|
+
|
3
|
+
module G5AuthenticatableApi
|
4
|
+
module Helpers
|
5
|
+
module Rails
|
6
|
+
def authenticate_api_user!
|
7
|
+
raise_auth_error if !(warden.try(:authenticated?) || token_validator.valid?)
|
8
|
+
end
|
9
|
+
|
10
|
+
def warden
|
11
|
+
request.env['warden']
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def token_validator
|
16
|
+
@token_validator ||= TokenValidator.new(request.params, request.headers)
|
17
|
+
end
|
18
|
+
|
19
|
+
def raise_auth_error
|
20
|
+
response.headers['WWW-Authenticate'] = token_validator.auth_response_header
|
21
|
+
render json: {error: 'Unauthorized'},
|
22
|
+
status: :unauthorized
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'g5_authenticatable_api/helpers/rails'
|
2
|
+
|
3
|
+
module G5AuthenticatableApi
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
initializer 'g5_authenticatable.helpers' do
|
6
|
+
ActiveSupport.on_load(:action_controller) do
|
7
|
+
include G5AuthenticatableApi::Helpers::Rails
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module G5AuthenticatableApi
|
2
|
+
class TokenValidator
|
3
|
+
attr_reader :error
|
4
|
+
|
5
|
+
def initialize(params={},headers={})
|
6
|
+
@params = params || {}
|
7
|
+
@headers = headers || {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def validate!
|
11
|
+
begin
|
12
|
+
auth_client.token_info
|
13
|
+
rescue StandardError => @error
|
14
|
+
raise error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid?
|
19
|
+
begin
|
20
|
+
validate!
|
21
|
+
true
|
22
|
+
rescue StandardError => e
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def access_token
|
28
|
+
@access_token ||= if @headers['Authorization']
|
29
|
+
parts = @headers['Authorization'].match(/Bearer (?<access_token>\S+)/)
|
30
|
+
parts['access_token']
|
31
|
+
else
|
32
|
+
@params['access_token']
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def auth_response_header
|
37
|
+
if error
|
38
|
+
auth_header = "Bearer"
|
39
|
+
|
40
|
+
if access_token
|
41
|
+
auth_header << " error=\"#{error_code}\""
|
42
|
+
auth_header << ",error_description=\"#{error_description}\"" if error_description
|
43
|
+
end
|
44
|
+
|
45
|
+
auth_header
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def auth_client
|
50
|
+
@auth_client ||= G5AuthenticationClient::Client.new(allow_password_credentials: 'false',
|
51
|
+
access_token: access_token)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def error_code
|
56
|
+
error_code = error.code if error.respond_to?(:code)
|
57
|
+
error_code || 'invalid_request'
|
58
|
+
end
|
59
|
+
|
60
|
+
def error_description
|
61
|
+
error_description = error.description if error.respond_to?(:description)
|
62
|
+
error_description
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/spec/dummy/Rakefile
ADDED
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require jquery
|
14
|
+
//= require jquery_ujs
|
15
|
+
//= require turbolinks
|
16
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|