warden-jwt_auth 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +3 -3
- data/lib/warden/jwt_auth.rb +23 -3
- data/lib/warden/jwt_auth/env_helper.rb +52 -0
- data/lib/warden/jwt_auth/header_parser.rb +2 -4
- data/lib/warden/jwt_auth/hooks.rb +8 -6
- data/lib/warden/jwt_auth/middleware/revocation_manager.rb +10 -7
- data/lib/warden/jwt_auth/strategy.rb +3 -3
- data/lib/warden/jwt_auth/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f24397de1422507d524eba4a8c60050e6a6abde
|
4
|
+
data.tar.gz: b767bf87c6b29a12da5a64b4367f619b8685568e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29f2e7ef4ea4de94a68b4cac0e394df30609fa706c6afb468d725000995a68c80227abd64392367b94fda770fe7884aac11041ecd742661d96eaa8045efb04c7
|
7
|
+
data.tar.gz: ab4e91316b5ca085c1f2f1f267656097d788a2e1e5ad1cf9face21402f569aa989264c57bdb8310512d7028a0e10351697abf13ece06512c0470f9bf72b49f93
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
6
|
|
7
|
+
## [0.2.1] - 2017-12-04
|
8
|
+
### Added
|
9
|
+
- Allow configuring classes as strings
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
- Take `PATH_INFO` as an empty string when it is not present
|
13
|
+
|
7
14
|
## [0.2.0] - 2017-11-23
|
8
15
|
### Added
|
9
16
|
- `fail!` with message
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ If what you need is a JWT authentication library for [devise](https://github.com
|
|
24
24
|
## Installation
|
25
25
|
|
26
26
|
```ruby
|
27
|
-
gem 'warden-jwt_auth', '~> 0.2.
|
27
|
+
gem 'warden-jwt_auth', '~> 0.2.1'
|
28
28
|
```
|
29
29
|
|
30
30
|
And then execute:
|
@@ -63,7 +63,7 @@ Currently, HS256 algorithm is the one in use.
|
|
63
63
|
|
64
64
|
### Warden scopes configuration
|
65
65
|
|
66
|
-
You have to map the warden scopes that will be authenticatable through JWT, with the user repositories from where these scope user records can be fetched.
|
66
|
+
You have to map the warden scopes that will be authenticatable through JWT, with the user repositories from where these scope user records can be fetched. If a string is supplied, the user repository will first be looked up as a constant.
|
67
67
|
|
68
68
|
For instance:
|
69
69
|
|
@@ -142,7 +142,7 @@ config.revocation_requests = [
|
|
142
142
|
|
143
143
|
**Important**: You are encouraged to delimit your regular expression with `^` and `$` to avoid unintentional matches.
|
144
144
|
|
145
|
-
Besides, you need to configure which revocation strategy will be used for each scope.
|
145
|
+
Besides, you need to configure which revocation strategy will be used for each scope. If a string is supplied, the revocation strategy will first be looked up as a constant.
|
146
146
|
|
147
147
|
```ruby
|
148
148
|
config.revocation_strategies = { user: RevocationStrategy }
|
data/lib/warden/jwt_auth.rb
CHANGED
@@ -25,7 +25,8 @@ module Warden
|
|
25
25
|
# Expiration time for tokens
|
26
26
|
setting :expiration_time, 3600
|
27
27
|
|
28
|
-
# A hash of warden scopes as keys and user repositories as values.
|
28
|
+
# A hash of warden scopes as keys and user repositories as values. The
|
29
|
+
# values can be either the constants themselves or the constant names.
|
29
30
|
#
|
30
31
|
# @see Interfaces::UserRepository
|
31
32
|
# @see Interfaces::User
|
@@ -56,8 +57,9 @@ module Warden
|
|
56
57
|
upcase_first_items(value)
|
57
58
|
end
|
58
59
|
|
59
|
-
# Hash with scopes as keys and
|
60
|
-
#
|
60
|
+
# Hash with scopes as keys and strategies to revoke tokens for that scope
|
61
|
+
# as values. The values can be either the constants themselves or the
|
62
|
+
# constant names.
|
61
63
|
#
|
62
64
|
# @example
|
63
65
|
# {
|
@@ -87,12 +89,30 @@ module Warden
|
|
87
89
|
end
|
88
90
|
|
89
91
|
Import = Dry::AutoInject(config)
|
92
|
+
|
93
|
+
config.instance_eval do
|
94
|
+
def mappings
|
95
|
+
constantize_values(super)
|
96
|
+
end
|
97
|
+
|
98
|
+
def revocation_strategies
|
99
|
+
constantize_values(super)
|
100
|
+
end
|
101
|
+
|
102
|
+
# :reek:UtilityFunction
|
103
|
+
def constantize_values(hash)
|
104
|
+
hash.each_with_object({}) do |(key, value), memo|
|
105
|
+
memo[key] = value.is_a?(String) ? Object.const_get(value) : value
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
90
109
|
end
|
91
110
|
end
|
92
111
|
|
93
112
|
require 'warden/jwt_auth/version'
|
94
113
|
require 'warden/jwt_auth/header_parser'
|
95
114
|
require 'warden/jwt_auth/payload_user_helper'
|
115
|
+
require 'warden/jwt_auth/env_helper'
|
96
116
|
require 'warden/jwt_auth/user_encoder'
|
97
117
|
require 'warden/jwt_auth/user_decoder'
|
98
118
|
require 'warden/jwt_auth/token_encoder'
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Warden
|
4
|
+
module JWTAuth
|
5
|
+
# Helper functions to centralize working with rack env.
|
6
|
+
#
|
7
|
+
# It follows
|
8
|
+
# [rack](http://www.rubydoc.info/github/rack/rack/file/SPEC#The_Environment)
|
9
|
+
# and [PEP 333](https://www.python.org/dev/peps/pep-0333/#environ-variables)
|
10
|
+
# conventions.
|
11
|
+
module EnvHelper
|
12
|
+
# Returns PATH_INFO environment variable
|
13
|
+
#
|
14
|
+
# @param env [Hash] Rack env
|
15
|
+
# @return [String]
|
16
|
+
def self.path_info(env)
|
17
|
+
env['PATH_INFO'] || ''
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns REQUEST_METHOD environment variable
|
21
|
+
#
|
22
|
+
# @param env [Hash] Rack env
|
23
|
+
# @return [String]
|
24
|
+
def self.request_method(env)
|
25
|
+
env['REQUEST_METHOD']
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns HTTP_AUTHORIZATION environment variable
|
29
|
+
#
|
30
|
+
# @param env [Hash] Rack env
|
31
|
+
# @return [String]
|
32
|
+
def self.authorization_header(env)
|
33
|
+
env['HTTP_AUTHORIZATION']
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a copy of `env` with value added to the `HTTP_AUTHORIZATION`
|
37
|
+
# environment variable.
|
38
|
+
#
|
39
|
+
# Be aware than `env` is not modified in place and still an updated copy
|
40
|
+
# is returned.
|
41
|
+
#
|
42
|
+
# @param env [Hash] Rack env
|
43
|
+
# @param value [String]
|
44
|
+
# @return [Hash] modified rack env
|
45
|
+
def self.set_authorization_header(env, value)
|
46
|
+
env = env.dup
|
47
|
+
env['HTTP_AUTHORIZATION'] = value
|
48
|
+
env
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -14,7 +14,7 @@ module Warden
|
|
14
14
|
# @return [String] JWT token
|
15
15
|
# @return [nil] if token is not present
|
16
16
|
def self.from_env(env)
|
17
|
-
auth = env
|
17
|
+
auth = EnvHelper.authorization_header(env)
|
18
18
|
return nil unless auth
|
19
19
|
method, token = auth.split
|
20
20
|
method == METHOD ? token : nil
|
@@ -27,9 +27,7 @@ module Warden
|
|
27
27
|
# @param token [String] JWT token
|
28
28
|
# @return [Hash] modified rack env
|
29
29
|
def self.to_env(env, token)
|
30
|
-
env
|
31
|
-
env['HTTP_AUTHORIZATION'] = "#{METHOD} #{token}"
|
32
|
-
env
|
30
|
+
EnvHelper.set_authorization_header(env, "#{METHOD} #{token}")
|
33
31
|
end
|
34
32
|
|
35
33
|
# Returns a copy of headers with token added in the `Authorization` key.
|
@@ -29,7 +29,9 @@ module Warden
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def token_should_be_added?(scope, env)
|
32
|
-
|
32
|
+
path_info = EnvHelper.path_info(env)
|
33
|
+
method = EnvHelper.request_method(env)
|
34
|
+
jwt_scope?(scope) && request_matches?(path_info, method)
|
33
35
|
end
|
34
36
|
|
35
37
|
def jwt_scope?(scope)
|
@@ -37,12 +39,12 @@ module Warden
|
|
37
39
|
jwt_scopes.include?(scope)
|
38
40
|
end
|
39
41
|
|
40
|
-
# :reek:
|
41
|
-
def request_matches?(
|
42
|
+
# :reek:ControlParameter
|
43
|
+
def request_matches?(path_info, method)
|
42
44
|
dispatch_requests.each do |tuple|
|
43
|
-
|
44
|
-
return true if
|
45
|
-
|
45
|
+
dispatch_method, dispatch_path = tuple
|
46
|
+
return true if path_info.match(dispatch_path) &&
|
47
|
+
method == dispatch_method
|
46
48
|
end
|
47
49
|
false
|
48
50
|
end
|
@@ -8,11 +8,12 @@ module Warden
|
|
8
8
|
# Debugging key added to `env`
|
9
9
|
ENV_KEY = 'warden-jwt_auth.revocation_manager'
|
10
10
|
|
11
|
-
attr_reader :app, :config
|
11
|
+
attr_reader :app, :config, :helper
|
12
12
|
|
13
13
|
def initialize(app)
|
14
14
|
@app = app
|
15
15
|
@config = JWTAuth.config
|
16
|
+
@helper = EnvHelper
|
16
17
|
end
|
17
18
|
|
18
19
|
def call(env)
|
@@ -26,17 +27,19 @@ module Warden
|
|
26
27
|
|
27
28
|
def revoke_token(env)
|
28
29
|
token = HeaderParser.from_env(env)
|
29
|
-
|
30
|
+
path_info = EnvHelper.path_info(env)
|
31
|
+
method = EnvHelper.request_method(env)
|
32
|
+
return unless token && token_should_be_revoked?(path_info, method)
|
30
33
|
TokenRevoker.new.call(token)
|
31
34
|
end
|
32
35
|
|
33
|
-
# :reek:
|
34
|
-
def token_should_be_revoked?(
|
36
|
+
# :reek:ControlParameter
|
37
|
+
def token_should_be_revoked?(path_info, method)
|
35
38
|
revocation_requests = config.revocation_requests
|
36
39
|
revocation_requests.each do |tuple|
|
37
|
-
|
38
|
-
return true if
|
39
|
-
|
40
|
+
revocation_method, revocation_path = tuple
|
41
|
+
return true if path_info.match(revocation_path) &&
|
42
|
+
method == revocation_method
|
40
43
|
end
|
41
44
|
false
|
42
45
|
end
|
@@ -8,7 +8,7 @@ module Warden
|
|
8
8
|
# `Authorization` request header
|
9
9
|
# :reek:PrimaDonnaMethod
|
10
10
|
class Strategy < Warden::Strategies::Base
|
11
|
-
# :reek:
|
11
|
+
# :reek:NilCheck
|
12
12
|
def valid?
|
13
13
|
!token.nil?
|
14
14
|
end
|
@@ -20,8 +20,8 @@ module Warden
|
|
20
20
|
def authenticate!
|
21
21
|
user = UserDecoder.new.call(token, scope)
|
22
22
|
success!(user)
|
23
|
-
rescue JWT::DecodeError =>
|
24
|
-
fail!(
|
23
|
+
rescue JWT::DecodeError => exception
|
24
|
+
fail!(exception.message)
|
25
25
|
end
|
26
26
|
|
27
27
|
private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: warden-jwt_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc Busqué
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-configurable
|
@@ -191,6 +191,7 @@ files:
|
|
191
191
|
- bin/setup
|
192
192
|
- docker-compose.yml
|
193
193
|
- lib/warden/jwt_auth.rb
|
194
|
+
- lib/warden/jwt_auth/env_helper.rb
|
194
195
|
- lib/warden/jwt_auth/errors.rb
|
195
196
|
- lib/warden/jwt_auth/header_parser.rb
|
196
197
|
- lib/warden/jwt_auth/hooks.rb
|