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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ac722c142dfc949c887f3bd913c19e9a743c6dc9503badaa967fc180b200344
4
- data.tar.gz: bbac43c4ad1611c136da5a66f544eea639262fa2cb01e6eb1853610ee630b0ca
3
+ metadata.gz: f7d2d71dd1671a97f1ce4f9181852e8cc7e0a651e91370aca09300c468dfbf86
4
+ data.tar.gz: f4fcef9ecc2977321ae3ec193a8be62c0735d08f0a564787ff581d3e65bc869a
5
5
  SHA512:
6
- metadata.gz: 7941fafb990e4d7aa8cb070963aba181b91d3d108fd4a4d6017618b15532d83876db3dc69a3fb962d5193adb61f82cad5874b7b65590880b99a6eb68117e0e6d
7
- data.tar.gz: b3d1a127bbe650df453b3158d81df5fd56dfcad9c9862ceaba502ca25dd45ad9c6a6764f65a481cd6a54989aa22b5cf10774a003efc97d949c782cdddc767660
6
+ metadata.gz: 482f861b69e7e05eb6d9b2308b2c0dfc402ac8a8bd01f200e14e04cafd24897adea376de29a6ad1fb6a52eeb08647303c10c344e097a45c1dea6730ace2a4bdf
7
+ data.tar.gz: 10ada294eda678f2d70c4780db32f33063a869d3caf25c481949cd5350f326bbeb6c5a60d96fa797ef3d1f2548c552edde731a28fd9667ee20a7d336ad936656
@@ -1,3 +1,3 @@
1
1
  module PrxAuth
2
- VERSION = "1.5.0"
2
+ VERSION = "1.6.0"
3
3
  end
@@ -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
- return @app.call(env) unless should_validate_token?(claims)
33
+ auth_validator = build_auth_validator(token)
30
34
 
31
- if valid?(claims, token)
32
- env['prx.auth'] = TokenData.new(claims)
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 valid?(claims, token)
42
- !expired?(claims) && @certificate.valid?(token)
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)
@@ -28,5 +28,5 @@ Gem::Specification.new do |spec|
28
28
 
29
29
  spec.add_dependency 'rack', '>= 1.5.2'
30
30
  spec.add_dependency 'json', '>= 1.8.1'
31
- spec.add_dependency 'json-jwt', '~> 1.11.0'
31
+ spec.add_dependency 'json-jwt', '~> 1.12.0'
32
32
  end
@@ -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
@@ -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(:valid?, false) do
39
- assert prxauth.call(env) == Rack::PrxAuth::INVALID_TOKEN
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(:expired?, true) do
47
- assert prxauth.call(env) == Rack::PrxAuth::INVALID_TOKEN
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.stub(:decode_token, claims) do
54
- prxauth.stub(:valid?, true) do
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.5.0
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: 2020-10-19 00:00:00.000000000 Z
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.11.0
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.11.0
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.1
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