roda-http-auth 0.1.2 → 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 +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
|
-
[](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
|