roda-http-auth 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +45 -39
- data/lib/roda/plugins/http_auth.rb +32 -38
- data/lib/roda/plugins/http_auth/version.rb +1 -1
- data/roda-http-auth.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ff92568175fbe77129586e375501c1ef08a420b766a6f841d51f46c86c70db6
|
4
|
+
data.tar.gz: 893b85397675601e3521ab339a9fd047c76c0d8ebdcaee7e8290bffc6ec62618
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1271d1c2d504363e7db7e067e2510eb4b61a2c544126b15ae5047a5135463e43b7aa35aa29db4377622aefdeea7f7b01ec8be32c1ec198500bbc937d9d98cc9c
|
7
|
+
data.tar.gz: cdc56c9d35aca78604ee22731443c5abd375401e324cec44a0d036cad3f576cfeb09ce20ac927771d8cd61dc5bdf4c2d9a96b16282d9949994db0730c688781f
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Roda Http Authorization
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/badosu/roda-
|
3
|
+
[![Build Status](https://travis-ci.org/badosu/roda-http-auth.png)](https://travis-ci.org/badosu/roda-http-auth)
|
4
4
|
|
5
5
|
Add http authorization methods to Roda.
|
6
6
|
|
@@ -13,49 +13,42 @@ plugin :http_auth
|
|
13
13
|
```
|
14
14
|
|
15
15
|
You can pass global options, in this context they'll be shared between all
|
16
|
-
`
|
16
|
+
`http_auth` calls.
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
plugin :http_auth, authenticator:
|
19
|
+
plugin :http_auth, authenticator: ->(user, pass) { [user, pass] == %w[foo bar] },
|
20
20
|
realm: 'Restricted Area', # default
|
21
21
|
schemes: %w[basic] # default
|
22
22
|
```
|
23
23
|
|
24
|
-
|
24
|
+
## Usage
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
Call `http_auth` inside the routes you want to authenticate the user, it will halt
|
27
|
+
the request with an empty response with status 401 if the authenticator is false.
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
{'Content-Type' => 'text/plain',
|
32
|
-
'Content-Length' => '0',
|
33
|
-
'WWW-Authenticate' => ('Basic realm="%s"' % opts[:realm])}
|
34
|
-
end, # default
|
35
|
-
```
|
36
|
-
|
37
|
-
The `unauthorized` option can receive a block to be invoked whenever the user
|
38
|
-
is unathorized:
|
29
|
+
You can provide an `unauthorized` block to be invoked whenever the user is
|
30
|
+
unathorized, it's executed in the context of the instance:
|
39
31
|
|
40
32
|
```ruby
|
41
|
-
plugin :http_auth, unauthorized:
|
42
|
-
logger.warn("Unathorized attempt to access #{r.path}!!")
|
43
|
-
end
|
44
|
-
```
|
33
|
+
plugin :http_auth, unauthorized: -> { view('401.html') }
|
45
34
|
|
46
|
-
|
35
|
+
# ...
|
47
36
|
|
48
|
-
|
49
|
-
|
37
|
+
r.root do
|
38
|
+
http_auth {|u, p| [u, p] == %w[foo bar] }
|
50
39
|
|
51
|
-
|
40
|
+
"If you can see this you were authorized! \
|
41
|
+
Otherwise you'll be served with the 401.html.erb template"
|
42
|
+
end
|
43
|
+
```
|
52
44
|
|
53
45
|
### Basic Auth
|
54
46
|
|
55
47
|
Basic authorization is the default method:
|
56
48
|
|
57
49
|
```ruby
|
58
|
-
|
50
|
+
# Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
|
51
|
+
http_auth { |user, pass| [user, pass] == ['Aladdin', 'open sesame'] }
|
59
52
|
```
|
60
53
|
|
61
54
|
### Schemes
|
@@ -70,19 +63,20 @@ plugin :http_auth, schemes: %w[bearer]
|
|
70
63
|
You can also whitelist schemes for a specific route:
|
71
64
|
|
72
65
|
```ruby
|
73
|
-
|
66
|
+
http_auth(schemes: %w[bearer]) { |token| token == '4t0k3n' }
|
74
67
|
```
|
75
68
|
|
76
69
|
### Scheme: Bearer
|
77
70
|
|
78
|
-
When the `Bearer`
|
79
|
-
|
71
|
+
When the `Bearer` scheme is passed, if whitelisted, the token is passed to
|
72
|
+
the authenticator:
|
80
73
|
|
81
74
|
```ruby
|
82
|
-
|
75
|
+
# Authorization: Bearer 4t0k3n
|
76
|
+
http_auth { |token| token == '4t0k3n' }
|
83
77
|
```
|
84
78
|
|
85
|
-
###
|
79
|
+
### Schemes with formatted parameters
|
86
80
|
|
87
81
|
For schemes that require formatted params authorization header, like `Digest`,
|
88
82
|
the scheme and the parsed params are passed to the authenticator:
|
@@ -102,13 +96,7 @@ Authorization: Digest username="Mufasa",
|
|
102
96
|
```
|
103
97
|
|
104
98
|
```ruby
|
105
|
-
|
106
|
-
```
|
107
|
-
|
108
|
-
## Test
|
109
|
-
|
110
|
-
```sh
|
111
|
-
bundle exec ruby test/*.rb
|
99
|
+
http_auth { |s, p| [s, p['username']] == ['digest', 'Mufasa'] }
|
112
100
|
```
|
113
101
|
|
114
102
|
## Warden
|
@@ -117,12 +105,30 @@ To avoid having your 401 responses intercepted by warden, you need to configure
|
|
117
105
|
the unauthenticated callback that is called just before the request is halted:
|
118
106
|
|
119
107
|
```ruby
|
120
|
-
plugin :http_auth, unauthorized:
|
108
|
+
plugin :http_auth, unauthorized: -> { env['warden'].custom_failure! }
|
109
|
+
```
|
110
|
+
|
111
|
+
## Additional Configuration
|
112
|
+
|
113
|
+
The header sent when the user is unauthorized can be configured via
|
114
|
+
`unauthorized_headers` and `realm` options, globally or locally:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
unauthorized_headers: ->(opts) do
|
118
|
+
{ 'WWW-Authenticate' => ('Basic realm="%s"' % opts[:realm]) }
|
119
|
+
end, # default
|
120
|
+
realm: "Restricted Area", # default
|
121
|
+
```
|
122
|
+
|
123
|
+
## Test
|
124
|
+
|
125
|
+
```sh
|
126
|
+
bundle exec ruby spec/*_spec.rb
|
121
127
|
```
|
122
128
|
|
123
129
|
## Contributing
|
124
130
|
|
125
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/badosu/roda-
|
131
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/badosu/roda-http-auth.
|
126
132
|
|
127
133
|
## License
|
128
134
|
|
@@ -5,14 +5,10 @@ module Roda::RodaPlugins
|
|
5
5
|
module HttpAuth
|
6
6
|
DEFAULTS = {
|
7
7
|
realm: "Restricted Area",
|
8
|
-
unauthorized_headers:
|
9
|
-
{'
|
10
|
-
'Content-Length' => '0',
|
11
|
-
'WWW-Authenticate' => ('Basic realm="%s"' % opts[:realm])}
|
12
|
-
end,
|
13
|
-
bad_request_headers: proc do |opts|
|
14
|
-
{'Content-Type' => 'text/plain', 'Content-Length' => '0'}
|
8
|
+
unauthorized_headers: ->(opts) do
|
9
|
+
{ 'WWW-Authenticate' => ('Basic realm="%s"' % opts[:realm]) }
|
15
10
|
end,
|
11
|
+
unauthorized: ->(r) {},
|
16
12
|
schemes: %w[basic]
|
17
13
|
}
|
18
14
|
|
@@ -22,50 +18,48 @@ module Roda::RodaPlugins
|
|
22
18
|
app.opts[:http_auth].freeze
|
23
19
|
end
|
24
20
|
|
25
|
-
module
|
21
|
+
module InstanceMethods
|
26
22
|
def http_auth(opts={}, &authenticator)
|
27
|
-
auth_opts = roda_class.opts[:http_auth].merge(opts)
|
23
|
+
auth_opts = request.roda_class.opts[:http_auth].merge(opts)
|
28
24
|
authenticator ||= auth_opts[:authenticator]
|
29
25
|
|
30
26
|
raise "Must provide an authenticator block" if authenticator.nil?
|
31
27
|
|
32
|
-
|
33
|
-
|
28
|
+
auth = Rack::Auth::Basic::Request.new(env)
|
29
|
+
|
30
|
+
unless auth.provided? && auth_opts[:schemes].include?(auth.scheme)
|
31
|
+
unauthorized(auth_opts)
|
32
|
+
end
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
credentials = if auth.basic?
|
35
|
+
auth.credentials
|
36
|
+
elsif auth.scheme == 'bearer'
|
37
|
+
[env['HTTP_AUTHORIZATION'].split(' ', 2).last]
|
38
|
+
else
|
39
|
+
http_auth = env['HTTP_AUTHORIZATION'].split(' ', 2)
|
40
|
+
.last
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
-
elsif auth.scheme == 'bearer'
|
43
|
-
[env['HTTP_AUTHORIZATION'].strip.split(' ').last]
|
44
|
-
else
|
45
|
-
[auth.scheme, _extract_credentials]
|
46
|
-
end
|
42
|
+
creds = !http_auth.include?('=') ? http_auth :
|
43
|
+
Rack::Auth::Digest::Params.parse(http_auth)
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
halt [400, auth_opts[:bad_request_headers].call(auth_opts), []]
|
45
|
+
[auth.scheme, creds]
|
46
|
+
end
|
47
|
+
|
48
|
+
if authenticator.call(*credentials)
|
49
|
+
env['REMOTE_USER'] = auth.username
|
50
|
+
else
|
51
|
+
unauthorized(auth_opts)
|
56
52
|
end
|
57
53
|
end
|
58
54
|
|
59
|
-
|
60
|
-
authorization = env['HTTP_AUTHORIZATION'].split(' ', 2).last
|
61
|
-
parts = authorization.split(',')
|
62
|
-
|
63
|
-
return parts.first if parts.one? && !parts.first.include?('=')
|
55
|
+
private
|
64
56
|
|
65
|
-
|
66
|
-
|
57
|
+
def unauthorized(opts)
|
58
|
+
response.status = 401
|
59
|
+
response.headers.merge!(opts[:unauthorized_headers].call(opts))
|
67
60
|
|
68
|
-
|
61
|
+
request.block_result(instance_exec(request, &opts[:unauthorized]))
|
62
|
+
request.halt response.finish
|
69
63
|
end
|
70
64
|
end
|
71
65
|
end
|
data/roda-http-auth.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roda-http-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amadeus Folego
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: roda
|
@@ -100,6 +100,20 @@ dependencies:
|
|
100
100
|
- - ">="
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: tilt
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
103
117
|
description: Add http authorization methods to Roda
|
104
118
|
email:
|
105
119
|
- amadeusfolego@gmail.com
|