prx_auth 1.5.0 → 1.6.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/lib/prx_auth/version.rb +1 -1
- data/lib/rack/prx_auth.rb +12 -29
- data/lib/rack/prx_auth/auth_validator.rb +51 -0
- data/lib/rack/prx_auth/token_data.rb +5 -1
- data/prx_auth.gemspec +1 -1
- data/test/rack/prx_auth/auth_validator_test.rb +111 -0
- data/test/rack/prx_auth_test.rb +16 -66
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7d2d71dd1671a97f1ce4f9181852e8cc7e0a651e91370aca09300c468dfbf86
|
4
|
+
data.tar.gz: f4fcef9ecc2977321ae3ec193a8be62c0735d08f0a564787ff581d3e65bc869a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 482f861b69e7e05eb6d9b2308b2c0dfc402ac8a8bd01f200e14e04cafd24897adea376de29a6ad1fb6a52eeb08647303c10c344e097a45c1dea6730ace2a4bdf
|
7
|
+
data.tar.gz: 10ada294eda678f2d70c4780db32f33063a869d3caf25c481949cd5350f326bbeb6c5a60d96fa797ef3d1f2548c552edde731a28fd9667ee20a7d336ad936656
|
data/lib/prx_auth/version.rb
CHANGED
data/lib/rack/prx_auth.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'json/jwt'
|
2
2
|
require 'rack/prx_auth/certificate'
|
3
3
|
require 'rack/prx_auth/token_data'
|
4
|
+
require 'rack/prx_auth/auth_validator'
|
4
5
|
require 'prx_auth'
|
5
6
|
|
6
7
|
module Rack
|
@@ -20,16 +21,21 @@ module Rack
|
|
20
21
|
@issuer = options[:issuer] || DEFAULT_ISS
|
21
22
|
end
|
22
23
|
|
24
|
+
def build_auth_validator(token)
|
25
|
+
AuthValidator.new(token, @certificate, @issuer)
|
26
|
+
end
|
27
|
+
|
23
28
|
def call(env)
|
24
29
|
return @app.call(env) unless env['HTTP_AUTHORIZATION']
|
25
30
|
|
26
31
|
token = env['HTTP_AUTHORIZATION'].split[1]
|
27
|
-
claims = decode_token(token)
|
28
32
|
|
29
|
-
|
33
|
+
auth_validator = build_auth_validator(token)
|
30
34
|
|
31
|
-
|
32
|
-
|
35
|
+
return @app.call(env) unless should_validate_token?(auth_validator)
|
36
|
+
|
37
|
+
if auth_validator.valid?
|
38
|
+
env['prx.auth'] = TokenData.new(auth_validator.claims)
|
33
39
|
@app.call(env)
|
34
40
|
else
|
35
41
|
INVALID_TOKEN
|
@@ -38,31 +44,8 @@ module Rack
|
|
38
44
|
|
39
45
|
private
|
40
46
|
|
41
|
-
def
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
def decode_token(token)
|
46
|
-
return {} if token.nil?
|
47
|
-
|
48
|
-
begin
|
49
|
-
JSON::JWT.decode(token, :skip_verification)
|
50
|
-
rescue JSON::JWT::InvalidFormat
|
51
|
-
{}
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def expired?(claims)
|
56
|
-
now = Time.now.to_i - 30 # 30 second clock jitter allowance
|
57
|
-
if claims['iat'] <= claims['exp']
|
58
|
-
now > claims['exp']
|
59
|
-
else
|
60
|
-
now > (claims['iat'] + claims['exp'])
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def should_validate_token?(claims)
|
65
|
-
claims['iss'] == @issuer
|
47
|
+
def should_validate_token?(auth_validator)
|
48
|
+
auth_validator.token_issuer_matches?
|
66
49
|
end
|
67
50
|
end
|
68
51
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'json/jwt'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class PrxAuth
|
5
|
+
class AuthValidator
|
6
|
+
|
7
|
+
attr_reader :issuer, :claims, :token
|
8
|
+
|
9
|
+
def initialize(token, certificate, issuer)
|
10
|
+
@token = token
|
11
|
+
@certificate = certificate
|
12
|
+
@issuer = issuer
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid?
|
16
|
+
valid_token_format? && !expired? && @certificate.valid?(token)
|
17
|
+
end
|
18
|
+
|
19
|
+
def claims
|
20
|
+
@claims ||= decode_token
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_token_format?
|
24
|
+
decode_token.present?
|
25
|
+
end
|
26
|
+
|
27
|
+
def decode_token
|
28
|
+
return {} if token.nil?
|
29
|
+
|
30
|
+
begin
|
31
|
+
JSON::JWT.decode(token, :skip_verification)
|
32
|
+
rescue JSON::JWT::InvalidFormat
|
33
|
+
{}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def expired?
|
38
|
+
now = Time.now.to_i - 30 # 30 second clock jitter allowance
|
39
|
+
if claims['iat'] <= claims['exp']
|
40
|
+
now > claims['exp']
|
41
|
+
else
|
42
|
+
now > (claims['iat'] + claims['exp'])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def token_issuer_matches?
|
47
|
+
claims['iss'] == @issuer
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -32,7 +32,11 @@ module Rack
|
|
32
32
|
def globally_authorized?(namespace, scope=nil)
|
33
33
|
authorized?(::PrxAuth::ResourceMap::WILDCARD_KEY, namespace, scope)
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
|
+
def authorized_account_ids(scope)
|
37
|
+
resources(::PrxAuth::Rails.configuration.namespace, scope).map(&:to_i)
|
38
|
+
end
|
39
|
+
|
36
40
|
private
|
37
41
|
|
38
42
|
def unpack_aur(aur)
|
data/prx_auth.gemspec
CHANGED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Rack::PrxAuth::AuthValidator do
|
4
|
+
let(:app) { Proc.new {|env| env } }
|
5
|
+
let(:auth_validator) { Rack::PrxAuth::AuthValidator.new(token, certificate, 'id.local.test') }
|
6
|
+
|
7
|
+
let(:token) { 'some.token.foo' }
|
8
|
+
|
9
|
+
let(:iat) { Time.now.to_i }
|
10
|
+
let(:exp) { 3600 }
|
11
|
+
let(:claims) { {'sub'=>3, 'exp'=>exp, 'iat'=>iat, 'token_type'=>'bearer', 'scope'=>nil, 'iss'=>'id.prx.org'} }
|
12
|
+
let(:certificate) { cert = Rack::PrxAuth::Certificate.new }
|
13
|
+
|
14
|
+
describe '#token_issuer_matches' do
|
15
|
+
it 'false if the token is from another issuer' do
|
16
|
+
auth_validator.stub(:claims, claims) do
|
17
|
+
refute auth_validator.token_issuer_matches?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'is false if the issuer in the validator does not match' do
|
22
|
+
auth_validator.stub(:issuer, 'id.foo.com') do
|
23
|
+
refute auth_validator.token_issuer_matches?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#valid?' do
|
29
|
+
it 'is false if token is invalid' do
|
30
|
+
auth_validator.stub(:claims, claims) do
|
31
|
+
refute auth_validator.valid?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'is false if the token is nil' do
|
36
|
+
certificate.stub(:valid?, true) do
|
37
|
+
auth_validator.stub(:token, nil) do
|
38
|
+
refute auth_validator.valid?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#expired?' do
|
45
|
+
|
46
|
+
def expired?(claims)
|
47
|
+
auth_validator.stub(:claims, claims) do
|
48
|
+
auth_validator.expired?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'with a malformed exp' do
|
53
|
+
let(:iat) { Time.now.to_i }
|
54
|
+
let(:exp) { 3600 }
|
55
|
+
|
56
|
+
it 'is expired if iat + exp are in the past' do
|
57
|
+
claims['iat'] -= 3631
|
58
|
+
|
59
|
+
assert expired?(claims)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'is not expired if iat + exp are in the future' do
|
63
|
+
claims['iat'] = Time.now.to_i - 3599
|
64
|
+
|
65
|
+
refute expired?(claims)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'allows a 30s clock jitter' do
|
69
|
+
claims['iat'] = Time.now.to_i - 3629
|
70
|
+
|
71
|
+
refute expired?(claims)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'with a corrected exp' do
|
76
|
+
let(:iat) { Time.now.to_i - 3600 }
|
77
|
+
let(:exp) { Time.now.to_i + 1 }
|
78
|
+
|
79
|
+
it 'is not expired if exp is in the future' do
|
80
|
+
refute expired?(claims)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'is expired if exp is in the past (with 30s jitter grace)' do
|
84
|
+
claims['exp'] = Time.now.to_i - 31
|
85
|
+
assert expired?(claims)
|
86
|
+
claims['exp'] = Time.now.to_i - 29
|
87
|
+
refute expired?(claims)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#decode_token' do
|
93
|
+
it 'should return an empty result for a nil token' do
|
94
|
+
auth_validator.stub(:token, nil) do
|
95
|
+
assert auth_validator.decode_token == {}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should return an empty result for an empty token' do
|
100
|
+
auth_validator.stub(:token, '') do
|
101
|
+
assert auth_validator.decode_token == {}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should return an empty result for a malformed token' do
|
106
|
+
auth_validator.stub(:token, token) do
|
107
|
+
assert auth_validator.decode_token == {}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/test/rack/prx_auth_test.rb
CHANGED
@@ -34,24 +34,34 @@ describe Rack::PrxAuth do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'returns 401 if verification fails' do
|
37
|
+
auth_validator = prxauth.build_auth_validator('sometoken')
|
38
|
+
|
37
39
|
JSON::JWT.stub(:decode, claims) do
|
38
|
-
prxauth.stub(:
|
39
|
-
|
40
|
+
prxauth.stub(:build_auth_validator, auth_validator) do
|
41
|
+
auth_validator.stub(:valid?, false) do
|
42
|
+
assert prxauth.call(env) == Rack::PrxAuth::INVALID_TOKEN
|
43
|
+
end
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
48
|
it 'returns 401 if access token has expired' do
|
49
|
+
auth_validator = prxauth.build_auth_validator('sometoken')
|
50
|
+
|
45
51
|
JSON::JWT.stub(:decode, claims) do
|
46
|
-
prxauth.stub(:
|
47
|
-
|
52
|
+
prxauth.stub(:build_auth_validator, auth_validator) do
|
53
|
+
auth_validator.stub(:expired?, true) do
|
54
|
+
assert prxauth.call(env) == Rack::PrxAuth::INVALID_TOKEN
|
55
|
+
end
|
48
56
|
end
|
49
57
|
end
|
50
58
|
end
|
51
59
|
|
52
60
|
it 'attaches claims to request params if verification passes' do
|
53
|
-
prxauth.
|
54
|
-
|
61
|
+
auth_validator = prxauth.build_auth_validator('sometoken')
|
62
|
+
|
63
|
+
JSON::JWT.stub(:decode, claims) do
|
64
|
+
prxauth.stub(:build_auth_validator, auth_validator) do
|
55
65
|
prxauth.call(env)['prx.auth'].tap do |token|
|
56
66
|
assert token.instance_of? Rack::PrxAuth::TokenData
|
57
67
|
assert token.user_id == claims['sub']
|
@@ -61,52 +71,6 @@ describe Rack::PrxAuth do
|
|
61
71
|
end
|
62
72
|
end
|
63
73
|
|
64
|
-
describe '#expired?' do
|
65
|
-
|
66
|
-
def expired?(claims)
|
67
|
-
prxauth.send(:expired?, claims)
|
68
|
-
end
|
69
|
-
|
70
|
-
describe 'with a malformed exp' do
|
71
|
-
let(:iat) { Time.now.to_i }
|
72
|
-
let(:exp) { 3600 }
|
73
|
-
|
74
|
-
it 'is expired if iat + exp are in the past' do
|
75
|
-
claims['iat'] -= 3631
|
76
|
-
|
77
|
-
assert expired?(claims)
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'is not expired if iat + exp are in the future' do
|
81
|
-
claims['iat'] = Time.now.to_i - 3599
|
82
|
-
|
83
|
-
refute expired?(claims)
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'allows a 30s clock jitter' do
|
87
|
-
claims['iat'] = Time.now.to_i - 3629
|
88
|
-
|
89
|
-
refute expired?(claims)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
describe 'with a corrected exp' do
|
94
|
-
let(:iat) { Time.now.to_i - 3600 }
|
95
|
-
let(:exp) { Time.now.to_i + 1 }
|
96
|
-
|
97
|
-
it 'is not expired if exp is in the future' do
|
98
|
-
refute expired?(claims)
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'is expired if exp is in the past (with 30s jitter grace)' do
|
102
|
-
claims['exp'] = Time.now.to_i - 31
|
103
|
-
assert expired?(claims)
|
104
|
-
claims['exp'] = Time.now.to_i - 29
|
105
|
-
refute expired?(claims)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
74
|
describe 'initialize' do
|
111
75
|
it 'takes a certificate location as an option' do
|
112
76
|
loc = nil
|
@@ -116,18 +80,4 @@ describe Rack::PrxAuth do
|
|
116
80
|
end
|
117
81
|
end
|
118
82
|
end
|
119
|
-
|
120
|
-
describe '#decode_token' do
|
121
|
-
it 'should return an empty result for a nil token' do
|
122
|
-
assert prxauth.send(:decode_token, nil) == {}
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'should return an empty result for an empty token' do
|
126
|
-
assert prxauth.send(:decode_token, {}) == {}
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'should return an empty result for a malformed token' do
|
130
|
-
assert prxauth.send(:decode_token, 'asdfsadfsad') == {}
|
131
|
-
end
|
132
|
-
end
|
133
83
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prx_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eve Asher
|
8
8
|
- Chris Rhoden
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-01-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -115,14 +115,14 @@ dependencies:
|
|
115
115
|
requirements:
|
116
116
|
- - "~>"
|
117
117
|
- !ruby/object:Gem::Version
|
118
|
-
version: 1.
|
118
|
+
version: 1.12.0
|
119
119
|
type: :runtime
|
120
120
|
prerelease: false
|
121
121
|
version_requirements: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
123
|
- - "~>"
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: 1.
|
125
|
+
version: 1.12.0
|
126
126
|
description: Specific to PRX. Will ignore tokens that were not issued by PRX.
|
127
127
|
email:
|
128
128
|
- eve@prx.org
|
@@ -144,11 +144,13 @@ files:
|
|
144
144
|
- lib/prx_auth/scope_list.rb
|
145
145
|
- lib/prx_auth/version.rb
|
146
146
|
- lib/rack/prx_auth.rb
|
147
|
+
- lib/rack/prx_auth/auth_validator.rb
|
147
148
|
- lib/rack/prx_auth/certificate.rb
|
148
149
|
- lib/rack/prx_auth/token_data.rb
|
149
150
|
- prx_auth.gemspec
|
150
151
|
- test/prx_auth/resource_map_test.rb
|
151
152
|
- test/prx_auth/scope_list_test.rb
|
153
|
+
- test/rack/prx_auth/auth_validator_test.rb
|
152
154
|
- test/rack/prx_auth/certificate_test.rb
|
153
155
|
- test/rack/prx_auth/token_data_test.rb
|
154
156
|
- test/rack/prx_auth_test.rb
|
@@ -157,7 +159,7 @@ homepage: https://github.com/PRX/prx_auth
|
|
157
159
|
licenses:
|
158
160
|
- MIT
|
159
161
|
metadata: {}
|
160
|
-
post_install_message:
|
162
|
+
post_install_message:
|
161
163
|
rdoc_options: []
|
162
164
|
require_paths:
|
163
165
|
- lib
|
@@ -172,14 +174,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
174
|
- !ruby/object:Gem::Version
|
173
175
|
version: '0'
|
174
176
|
requirements: []
|
175
|
-
rubygems_version: 3.0.
|
176
|
-
signing_key:
|
177
|
+
rubygems_version: 3.0.3
|
178
|
+
signing_key:
|
177
179
|
specification_version: 4
|
178
180
|
summary: Utilites for parsing PRX JWTs and Rack middleware that verifies and attaches
|
179
181
|
the token's claims to env.
|
180
182
|
test_files:
|
181
183
|
- test/prx_auth/resource_map_test.rb
|
182
184
|
- test/prx_auth/scope_list_test.rb
|
185
|
+
- test/rack/prx_auth/auth_validator_test.rb
|
183
186
|
- test/rack/prx_auth/certificate_test.rb
|
184
187
|
- test/rack/prx_auth/token_data_test.rb
|
185
188
|
- test/rack/prx_auth_test.rb
|