prx_auth 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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