fridge 0.2.4 → 0.4.2

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
- SHA1:
3
- metadata.gz: baa2d0014ae145e09c68dc53c816938ad272aa3d
4
- data.tar.gz: 7f34e028cb347f9da11e1d52d6f7443dc7f470bb
2
+ SHA256:
3
+ metadata.gz: 769896062879cb0dc6c7c69f095a5cedab11beaa0c30cb3e302dfc15eb842343
4
+ data.tar.gz: 657ca035209d5be3fcb78aaa74cc418bf764726622ccc3d90e0cab900ad4cf13
5
5
  SHA512:
6
- metadata.gz: 586f9c3edb3356d64068ca3b9c43741411238423b6cdb0d6a63041fed790b13e47c3d1d43c7ea6ef1c4e290b04f03cf253e4a6da40a2d0d9a89b01d72cb866fa
7
- data.tar.gz: 7d3dff29fffe39c8f656180e091639f4b2139a513fa024e2d0d189f5436cb4d39f2dacab4867987e57e781380359a3281e3d61fee5db8fe5a8fff723bc68ed91
6
+ metadata.gz: 1500d9599ef57f700c52c2362086a3c9e0ac1853c2182e72e1f24ffe0583ccdc38bcaca4d7c9e53b792d93b164ae7ac1510af721e7b1359e2e07998da44388b2
7
+ data.tar.gz: e18539fb6ae2d73dac73005348bc78015dc2a708e6d4e3f10b7b430ed8368f16f73d58d876ca6afdfb3dcf41d41b165d4291eac3ef6cb11c03c61ff87574fc72
@@ -0,0 +1 @@
1
+ * @dawenster
@@ -1,3 +1,5 @@
1
+ sudo: false
1
2
  rvm:
2
- - 2.0.0
3
- - jruby
3
+ - 2.2
4
+ - 2.5
5
+ - 2.6
data/Gemfile CHANGED
@@ -1,4 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'activesupport', '~> 4.0'
4
+ gem 'nokogiri', '~> 1.9.1'
5
+
3
6
  # Specify your gem's dependencies in fridge.gemspec
4
7
  gemspec
data/README.md CHANGED
@@ -80,4 +80,4 @@ store_session_cookie(access_token)
80
80
 
81
81
  MIT License, see [LICENSE](LICENSE.md) for details.
82
82
 
83
- Copyright (c) 2014 [Aptible](https://www.aptible.com), Frank Macreery, and contributors.
83
+ Copyright (c) 2019 [Aptible](https://www.aptible.com) and contributors.
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
 
@@ -16,17 +17,17 @@ Gem::Specification.new do |spec|
16
17
  spec.license = 'MIT'
17
18
 
18
19
  spec.files = `git ls-files`.split($RS)
19
- spec.test_files = spec.files.grep(/^spec\//)
20
+ spec.test_files = spec.files.grep(%r{^spec/})
20
21
  spec.require_paths = ['lib']
21
22
 
22
23
  spec.add_dependency 'gem_config'
23
- spec.add_dependency 'jwt', '~> 0.1.13'
24
+ spec.add_dependency 'jwt', '~> 1.5.6'
24
25
 
25
- spec.add_development_dependency 'bundler', '~> 1.5'
26
26
  spec.add_development_dependency 'aptible-tasks'
27
- spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'bundler', '~> 1.5'
28
+ spec.add_development_dependency 'pry'
28
29
  spec.add_development_dependency 'rails'
29
- spec.add_development_dependency 'rspec', '~> 2.0'
30
+ spec.add_development_dependency 'rake'
31
+ spec.add_development_dependency 'rspec', '~> 3.0'
30
32
  spec.add_development_dependency 'rspec-rails'
31
- spec.add_development_dependency 'pry'
32
33
  end
@@ -4,6 +4,7 @@ require 'fridge/version'
4
4
  require 'fridge/access_token'
5
5
  require 'fridge/serialization_error'
6
6
  require 'fridge/invalid_token'
7
+ require 'fridge/expired_token'
7
8
 
8
9
  require 'fridge/railtie' if defined?(Rails)
9
10
 
@@ -14,7 +15,9 @@ module Fridge
14
15
  has :private_key, classes: [String]
15
16
  has :public_key, classes: [String]
16
17
 
17
- has :signing_algorithm, values: %w(RS512 RS256), default: 'RS512'
18
+ # rubocop:disable Style/PercentLiteralDelimiters
19
+ has :signing_algorithm, values: %w[RS512 RS256], default: 'RS512'
20
+ # rubocop:enable Style/PercentLiteralDelimiters
18
21
 
19
22
  # A validator must raise an exception or return a false value for an
20
23
  # invalid token
@@ -2,10 +2,9 @@ require 'jwt'
2
2
 
3
3
  module Fridge
4
4
  class AccessToken
5
- attr_accessor :id, :issuer, :subject, :scope, :expires_at,
5
+ attr_accessor :id, :issuer, :subject, :scope, :expires_at, :actor,
6
6
  :jwt, :attributes
7
7
 
8
- # rubocop:disable MethodLength
9
8
  def initialize(jwt_or_options = nil)
10
9
  options = case jwt_or_options
11
10
  when String
@@ -15,13 +14,12 @@ module Fridge
15
14
  when Hash then jwt_or_options
16
15
  else {}
17
16
  end
18
- [:id, :issuer, :subject, :scope, :expires_at].each do |key|
17
+
18
+ [:id, :issuer, :subject, :scope, :expires_at, :actor].each do |key|
19
19
  send "#{key}=", options.delete(key)
20
20
  end
21
- self.attributes = options.reject { |_, v| v.nil? }
22
- self.attributes = Hash[attributes.map { |k, v| [k.to_sym, v] }]
21
+ self.attributes = options
23
22
  end
24
- # rubocop:enable MethodLength
25
23
 
26
24
  def to_s
27
25
  serialize
@@ -29,38 +27,36 @@ module Fridge
29
27
 
30
28
  def serialize
31
29
  return jwt if jwt
30
+
32
31
  validate_parameters!
33
32
  validate_private_key!
34
33
  encode_and_sign
35
34
  end
36
35
 
37
36
  def encode_and_sign
38
- JWT.encode({
39
- id: id,
40
- iss: issuer,
41
- sub: subject,
42
- scope: scope,
43
- exp: expires_at.to_i
44
- }.merge(attributes), private_key, algorithm)
45
- rescue
37
+ h = {}
38
+ [:id, :issuer, :subject, :scope, :expires_at, :actor].each do |key|
39
+ h[key] = send(key)
40
+ end
41
+ h.merge!(attributes)
42
+ h = encode_for_jwt(h)
43
+ JWT.encode(h, private_key, algorithm)
44
+ rescue StandardError
46
45
  raise SerializationError, 'Invalid private key or signing algorithm'
47
46
  end
48
47
 
49
- # rubocop:disable MethodLength
50
48
  def decode_and_verify(jwt)
51
- hash = JWT.decode(jwt, public_key)
52
- base = {
53
- id: hash.delete('id'),
54
- issuer: hash.delete('iss'),
55
- subject: hash.delete('sub'),
56
- scope: hash.delete('scope'),
57
- expires_at: Time.at(hash.delete('exp'))
58
- }
59
- base.merge(hash)
60
- rescue JWT::DecodeError
61
- raise InvalidToken, 'Invalid access token'
49
+ payload, _header = JWT.decode(jwt, public_key, true, algorithm: algorithm)
50
+ decode_from_jwt(payload)
51
+ rescue JWT::ExpiredSignature => e
52
+ raise ExpiredToken, e.message
53
+ rescue JWT::DecodeError => e
54
+ raise InvalidToken, e.message
55
+ end
56
+
57
+ def downgrade
58
+ self.scope = 'read'
62
59
  end
63
- # rubocop:enable MethodLength
64
60
 
65
61
  def valid?
66
62
  !expired?
@@ -72,8 +68,9 @@ module Fridge
72
68
 
73
69
  def private_key
74
70
  return unless config.private_key
71
+
75
72
  @private_key ||= OpenSSL::PKey::RSA.new(config.private_key)
76
- rescue
73
+ rescue StandardError
77
74
  nil
78
75
  end
79
76
 
@@ -83,7 +80,7 @@ module Fridge
83
80
  elsif config.public_key
84
81
  @public_key ||= OpenSSL::PKey::RSA.new(config.public_key)
85
82
  end
86
- rescue
83
+ rescue StandardError
87
84
  nil
88
85
  end
89
86
 
@@ -105,19 +102,72 @@ module Fridge
105
102
  end
106
103
  end
107
104
 
105
+ def respond_to_missing?(method, include_private = false)
106
+ attributes.key?(method) || super
107
+ end
108
+
108
109
  def validate_parameters!
109
110
  [:subject, :expires_at].each do |attribute|
110
111
  next if send(attribute)
111
- fail SerializationError, "Missing attribute: #{attribute}"
112
+
113
+ raise SerializationError, "Missing attribute: #{attribute}"
112
114
  end
113
115
  end
114
116
 
115
117
  def validate_private_key!
116
- fail SerializationError, 'No private key configured' unless private_key
118
+ raise SerializationError, 'No private key configured' unless private_key
117
119
  end
118
120
 
119
121
  def validate_public_key!
120
- fail SerializationError, 'No public key configured' unless public_key
122
+ raise SerializationError, 'No public key configured' unless public_key
123
+ end
124
+
125
+ # Internally, we use "subject" to refer to "sub", and so on. We also
126
+ # represent some objects (expiry) differently. These functions do the
127
+ # mapping from Fridge to JWT and vice-versa.
128
+
129
+ def encode_for_jwt(hash)
130
+ hash = hash.dup
131
+
132
+ out = {
133
+ id: hash.delete(:id),
134
+ iss: hash.delete(:issuer),
135
+ sub: hash.delete(:subject),
136
+ scope: hash.delete(:scope)
137
+ }.delete_if { |_, v| v.nil? }
138
+
139
+ # Unfortunately, nil.to_i returns 0, which means we can't
140
+ # easily clean out exp if we include it although it wasn't passed
141
+ # in like we do for other keys. So, we only include it if it's
142
+ # actually passed in and non-nil. Either way, we delete the keys.
143
+ hash.delete(:expires_at).tap { |e| out[:exp] = e.to_i if e }
144
+ hash.delete(:actor).tap { |a| out[:act] = encode_for_jwt(a) if a }
145
+
146
+ # Extra attributes passed through as-is
147
+ out.merge!(hash)
148
+
149
+ out
150
+ end
151
+
152
+ def decode_from_jwt(hash)
153
+ hash = hash.dup
154
+
155
+ out = {
156
+ id: hash.delete('id'),
157
+ issuer: hash.delete('iss'),
158
+ subject: hash.delete('sub'),
159
+ scope: hash.delete('scope')
160
+ }.delete_if { |_, v| v.nil? }
161
+
162
+ hash.delete('exp').tap { |e| out[:expires_at] = Time.at(e) if e }
163
+ hash.delete('act').tap { |a| out[:actor] = decode_from_jwt(a) if a }
164
+
165
+ # Extra attributes
166
+ hash.delete_if { |_, v| v.nil? }
167
+ hash = Hash[hash.map { |k, v| [k.to_sym, v] }]
168
+ out.merge!(hash)
169
+
170
+ out
121
171
  end
122
172
  end
123
173
  end
@@ -0,0 +1,4 @@
1
+ module Fridge
2
+ class ExpiredToken < InvalidToken
3
+ end
4
+ end
@@ -15,8 +15,13 @@ module Fridge
15
15
  current_token.subject if current_token
16
16
  end
17
17
 
18
+ def token_actor
19
+ current_token.actor if current_token
20
+ end
21
+
18
22
  def current_token
19
23
  return unless bearer_token
24
+
20
25
  @current_token ||= AccessToken.new(bearer_token).tap do |token|
21
26
  validate_token!(token)
22
27
  end
@@ -31,12 +36,17 @@ module Fridge
31
36
  session_token.subject if session_token
32
37
  end
33
38
 
39
+ def session_actor
40
+ session_token.actor if session_token
41
+ end
42
+
34
43
  def session_token
35
44
  return unless session_cookie
45
+
36
46
  @session_token ||= AccessToken.new(session_cookie).tap do |token|
37
- validate_token!(token)
47
+ validate_token!(token).downgrade
38
48
  end
39
- rescue
49
+ rescue StandardError
40
50
  clear_session_cookie
41
51
  end
42
52
 
@@ -44,7 +54,7 @@ module Fridge
44
54
  def validate_token(access_token)
45
55
  validator = Fridge.configuration.validator
46
56
  validator.call(access_token) && access_token
47
- rescue
57
+ rescue StandardError
48
58
  false
49
59
  end
50
60
 
@@ -54,7 +64,7 @@ module Fridge
54
64
  if validator.call(access_token)
55
65
  access_token
56
66
  else
57
- fail InvalidToken
67
+ raise InvalidToken, 'Rejected by validator'
58
68
  end
59
69
  end
60
70
 
@@ -83,7 +93,7 @@ module Fridge
83
93
  end
84
94
 
85
95
  def write_shared_cookie(name, value, options = {})
86
- fail 'Can only write string cookie values' unless value.is_a?(String)
96
+ raise 'Can only write string cookie values' unless value.is_a?(String)
87
97
 
88
98
  cookies[name] = {
89
99
  value: value,
@@ -95,9 +105,10 @@ module Fridge
95
105
  cookies[name]
96
106
  end
97
107
 
98
- def fetch_shared_cookie(name, &block)
108
+ def fetch_shared_cookie(name)
99
109
  return read_shared_cookie(name) if read_shared_cookie(name)
100
- write_shared_cookie(block.call)
110
+
111
+ write_shared_cookie(yield)
101
112
  end
102
113
 
103
114
  def delete_shared_cookie(name)
@@ -1,3 +1,3 @@
1
1
  module Fridge
2
- VERSION = '0.2.4'
2
+ VERSION = '0.4.2'.freeze
3
3
  end
@@ -1,7 +1,3 @@
1
- require 'active_support/all'
2
- require 'action_controller'
3
- require 'action_dispatch'
4
-
5
1
  module Rails
6
2
  class App
7
3
  def env_config
@@ -10,6 +6,7 @@ module Rails
10
6
 
11
7
  def routes
12
8
  return @routes if defined?(@routes)
9
+
13
10
  @routes = ActionDispatch::Routing::RouteSet.new
14
11
  @routes.draw do
15
12
  resources :posts
@@ -19,6 +16,6 @@ module Rails
19
16
  end
20
17
 
21
18
  def self.application
22
- @app ||= App.new
19
+ @application ||= App.new
23
20
  end
24
21
  end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'json'
2
3
 
3
4
  describe Fridge::AccessToken do
4
5
  describe '#initialize' do
@@ -13,19 +14,39 @@ describe Fridge::AccessToken do
13
14
  end
14
15
 
15
16
  it 'should accept a JWT' do
16
- jwt = JWT.encode({ id: 'foobar', exp: 0 }, private_key, 'RS512')
17
+ jwt = JWT.encode(
18
+ { id: 'foobar', exp: Time.now.to_i + 10 },
19
+ private_key, 'RS512'
20
+ )
17
21
  access_token = described_class.new(jwt)
18
22
  expect(access_token.id).to eq 'foobar'
19
23
  end
20
24
 
21
25
  it 'should raise an error on an invalid JWT' do
22
- expect { described_class.new('foobar') }.to raise_error
26
+ expect { described_class.new('foobar') }
27
+ .to raise_error Fridge::InvalidToken
23
28
  end
24
29
 
25
30
  it 'should raise an error on an incorrectly signed JWT' do
26
31
  jwt = JWT.encode({ id: 'foobar' }, OpenSSL::PKey::RSA.new(1024), 'RS512')
27
32
  expect { described_class.new(jwt) }.to raise_error Fridge::InvalidToken
28
33
  end
34
+
35
+ it 'should raise an error on an expired JWT' do
36
+ jwt = JWT.encode(
37
+ { id: 'foobar', exp: Time.now.to_i - 10 },
38
+ private_key, 'RS512'
39
+ )
40
+ expect { described_class.new(jwt) }.to raise_error(Fridge::ExpiredToken)
41
+ end
42
+
43
+ # http://bit.ly/jwt-none-vulnerability
44
+ it 'should raise an error with { "alg": "none" }' do
45
+ jwt = "#{Base64.encode64({ typ: 'JWT', alg: 'none' }.to_json).chomp}." \
46
+ "#{Base64.encode64({ id: 'foobar' }.to_json).chomp}"
47
+ expect(JWT.decode(jwt, nil, false)[0]).to eq('id' => 'foobar')
48
+ expect { described_class.new(jwt) }.to raise_error Fridge::InvalidToken
49
+ end
29
50
  end
30
51
 
31
52
  describe '#serialize' do
@@ -72,8 +93,8 @@ describe Fridge::AccessToken do
72
93
  end
73
94
 
74
95
  it 'should represent :exp in seconds since the epoch' do
75
- hash = JWT.decode(subject.serialize, public_key)
76
- expect(hash['exp']).to be_a Fixnum
96
+ hash, = JWT.decode(subject.serialize, public_key)
97
+ expect(hash['exp']).to be_a Integer
77
98
  end
78
99
 
79
100
  it 'should be deterministic' do
@@ -93,12 +114,43 @@ describe Fridge::AccessToken do
93
114
 
94
115
  expect(copy.attributes[:foo]).to eq 'bar'
95
116
  expect(copy.foo).to eq 'bar'
117
+ expect(copy.respond_to?(:foo)).to be_truthy
118
+ expect(copy.respond_to?(:bar)).to be_falsey
96
119
  end
97
120
 
98
121
  it 'should raise an error if required attributes are missing' do
99
122
  subject.subject = nil
100
123
  expect { subject.serialize }.to raise_error Fridge::SerializationError
101
124
  end
125
+
126
+ it 'should encode and decode :actor as :act' do
127
+ # The `act` field can recursively encode additional
128
+ # claims, so we check those too.
129
+ actor = { subject: 'foo', username: 'test', actor: { subject: 'bar' } }
130
+ subject = described_class.new(options.merge(actor: actor))
131
+
132
+ # The JWT lib will return everything as strings, so we'll
133
+ # test that, although eventually we'll want to see symbols back.
134
+ actor_s = { 'sub' => 'foo', 'username' => 'test',
135
+ 'act' => { 'sub' => 'bar' } }
136
+ hash, = JWT.decode(subject.serialize, public_key)
137
+ expect(hash['act']).to eq(actor_s)
138
+
139
+ # Now, check that we properly get symbols back
140
+ new = described_class.new(subject.serialize)
141
+ expect(new.actor).to eq(actor)
142
+ end
143
+
144
+ it 'should be idempotent' do
145
+ subject = described_class.new(options)
146
+ expect(subject.serialize).to eq(subject.serialize)
147
+ end
148
+
149
+ it 'should be idempotent with an actor' do
150
+ actor = { subject: 'foo', username: 'test', actor: { subject: 'bar' } }
151
+ subject = described_class.new(options.merge(actor: actor))
152
+ expect(subject.serialize).to eq(subject.serialize)
153
+ end
102
154
  end
103
155
 
104
156
  describe '#expired?' do
@@ -117,4 +169,10 @@ describe Fridge::AccessToken do
117
169
  expect(subject).not_to be_expired
118
170
  end
119
171
  end
172
+
173
+ describe '#downgrade' do
174
+ it 'sets the token scope to :read' do
175
+ expect { subject.downgrade }.to change(subject, :scope).to('read')
176
+ end
177
+ end
120
178
  end
@@ -1,204 +1,218 @@
1
1
  require 'spec_helper'
2
2
  require 'fixtures/app'
3
- require 'fixtures/controller'
4
- require 'rspec/rails'
5
3
 
6
- # http://say26.com/rspec-testing-controllers-outside-of-a-rails-application
7
- describe Controller, type: :controller do
8
- context Fridge::RailsHelpers do
9
- let(:organization_url) do
10
- "https://auth.aptible.com/users/#{SecureRandom.uuid}"
4
+ describe Fridge::RailsHelpers do
5
+ include RSpec::Rails::ControllerExampleGroup
6
+
7
+ controller(ActionController::Base) { include Fridge::RailsHelpers }
8
+
9
+ let(:organization_url) do
10
+ "https://auth.aptible.com/users/#{SecureRandom.uuid}"
11
+ end
12
+ let(:private_key) { OpenSSL::PKey::RSA.new(1024) }
13
+ let(:public_key) { OpenSSL::PKey::RSA.new(private_key.public_key) }
14
+
15
+ let(:options) do
16
+ {
17
+ subject: "https://auth.aptible.com/users/#{SecureRandom.uuid}",
18
+ expires_at: Time.now + 3600
19
+ }
20
+ end
21
+ let(:access_token) { Fridge::AccessToken.new(options) }
22
+
23
+ let(:cookies) { controller.send(:cookies) }
24
+
25
+ before { Fridge.configuration.private_key = private_key.to_s }
26
+ before { Fridge.configuration.public_key = public_key.to_s }
27
+
28
+ describe '#bearer_token' do
29
+ it 'returns the bearer token from the Authorization: header' do
30
+ request.env['HTTP_AUTHORIZATION'] = 'Bearer foobar'
31
+ expect(controller.bearer_token).to eq 'foobar'
11
32
  end
12
- let(:private_key) { OpenSSL::PKey::RSA.new(1024) }
13
- let(:public_key) { OpenSSL::PKey::RSA.new(private_key.public_key) }
14
33
 
15
- let(:options) do
16
- {
17
- subject: "https://auth.aptible.com/users/#{SecureRandom.uuid}",
18
- expires_at: Time.now + 3600
19
- }
34
+ it 'returns nil in the absence of an Authorization: header' do
35
+ request.env['HTTP_AUTHORIZATION'] = nil
36
+ expect(controller.bearer_token).to be_nil
20
37
  end
21
- let(:access_token) { Fridge::AccessToken.new(options) }
38
+ end
22
39
 
23
- let(:cookies) { controller.send(:cookies) }
40
+ describe '#token_subject' do
41
+ it 'returns the subject encoded in the token' do
42
+ controller.stub(:current_token) { access_token }
43
+ expect(controller.token_subject).to eq access_token.subject
44
+ end
24
45
 
25
- before { Fridge.configuration.private_key = private_key.to_s }
26
- before { Fridge.configuration.public_key = public_key.to_s }
46
+ it 'returns nil if no token is present' do
47
+ controller.stub(:current_token) { nil }
48
+ expect(controller.token_subject).to be_nil
49
+ end
50
+ end
27
51
 
28
- describe '#bearer_token' do
29
- it 'returns the bearer token from the Authorization: header' do
30
- request.env['HTTP_AUTHORIZATION'] = 'Bearer foobar'
31
- expect(controller.bearer_token).to eq 'foobar'
32
- end
52
+ describe '#token_scope' do
53
+ it 'returns the scope encoded in the token' do
54
+ controller.stub(:current_token) { access_token }
55
+ expect(controller.token_scope).to eq access_token.scope
56
+ end
33
57
 
34
- it 'returns nil in the absence of an Authorization: header' do
35
- request.env['HTTP_AUTHORIZATION'] = nil
36
- expect(controller.bearer_token).to be_nil
37
- end
58
+ it 'returns nil if no token is present' do
59
+ controller.stub(:current_token) { nil }
60
+ expect(controller.token_scope).to be_nil
38
61
  end
62
+ end
39
63
 
40
- describe '#token_subject' do
41
- it 'returns the subject encoded in the token' do
42
- controller.stub(:current_token) { access_token }
43
- expect(controller.token_subject).to eq access_token.subject
44
- end
64
+ describe '#current_token' do
65
+ before { controller.stub(:bearer_token) { access_token.serialize } }
45
66
 
46
- it 'returns nil if no token is present' do
47
- controller.stub(:current_token) { nil }
48
- expect(controller.token_subject).to be_nil
49
- end
67
+ it 'should raise an error if the token is not a valid JWT' do
68
+ controller.stub(:bearer_token) { 'foobar' }
69
+ expect { controller.current_token }.to raise_error Fridge::InvalidToken
50
70
  end
51
71
 
52
- describe '#token_scope' do
53
- it 'returns the scope encoded in the token' do
54
- controller.stub(:current_token) { access_token }
55
- expect(controller.token_scope).to eq access_token.scope
56
- end
57
-
58
- it 'returns nil if no token is present' do
59
- controller.stub(:current_token) { nil }
60
- expect(controller.token_scope).to be_nil
61
- end
72
+ it 'should raise an error if the token has expired' do
73
+ access_token.expires_at = Time.now - 3600
74
+ expect { controller.current_token }.to raise_error Fridge::InvalidToken
62
75
  end
63
76
 
64
- describe '#current_token' do
65
- before { controller.stub(:bearer_token) { access_token.serialize } }
77
+ it 'should raise an error if custom validation fails' do
78
+ Fridge.configuration.validator = ->(_) { false }
79
+ expect { controller.current_token }.to raise_error Fridge::InvalidToken
80
+ end
66
81
 
67
- it 'should raise an error if the token is not a valid JWT' do
68
- controller.stub(:bearer_token) { 'foobar' }
69
- expect { controller.current_token }.to raise_error Fridge::InvalidToken
70
- end
82
+ it 'should not raise an error if a valid token is passed' do
83
+ expect { controller.current_token }.not_to raise_error
84
+ end
71
85
 
72
- it 'should raise an error if the token has expired' do
73
- access_token.expires_at = Time.now - 3600
74
- expect { controller.current_token }.to raise_error Fridge::InvalidToken
75
- end
86
+ it 'should return the token if a valid token is passed' do
87
+ expect(controller.current_token.id).to eq access_token.id
88
+ end
89
+ end
76
90
 
77
- it 'should raise an error if custom validation fails' do
78
- Fridge.configuration.validator = ->(_) { false }
79
- expect { controller.current_token }.to raise_error Fridge::InvalidToken
80
- end
91
+ describe '#session_subject' do
92
+ it 'returns the subject encoded in the session' do
93
+ controller.stub(:session_token) { access_token }
94
+ expect(controller.session_subject).to eq access_token.subject
95
+ end
81
96
 
82
- it 'should not raise an error if a valid token is passed' do
83
- expect { controller.current_token }.not_to raise_error
84
- end
97
+ it 'returns nil if no session is present' do
98
+ controller.stub(:session_token) { nil }
99
+ expect(controller.session_subject).to be_nil
100
+ end
101
+ end
85
102
 
86
- it 'should return the token if a valid token is passed' do
87
- expect(controller.current_token.id).to eq access_token.id
88
- end
103
+ describe '#session_token' do
104
+ it 'should delete all cookies on error' do
105
+ cookies[:fridge_session] = 'foobar'
106
+ controller.session_token
107
+ expect(cookies.deleted?(:fridge_session, domain: :all)).to be true
89
108
  end
90
109
 
91
- describe '#session_subject' do
92
- it 'returns the subject encoded in the session' do
93
- controller.stub(:session_token) { access_token }
94
- expect(controller.session_subject).to eq access_token.subject
95
- end
110
+ it 'should return nil on error' do
111
+ cookies[:fridge_session] = 'foobar'
112
+ expect(controller.session_token).to be_nil
113
+ end
96
114
 
97
- it 'returns nil if no session is present' do
98
- controller.stub(:session_token) { nil }
99
- expect(controller.session_subject).to be_nil
100
- end
115
+ it 'should return the token stored in :fridge_session' do
116
+ cookies[:fridge_session] = access_token.serialize
117
+ expect(controller.session_token.id).to eq access_token.id
101
118
  end
102
119
 
103
- describe '#session_token' do
104
- it 'should delete all cookies on error' do
105
- cookies[:fridge_session] = 'foobar'
106
- controller.session_token
107
- expect(cookies.deleted?(:fridge_session, domain: :all)).to be_true
108
- end
120
+ context 'with a non-:read scope' do
121
+ before { options.merge!(scope: 'manage') }
109
122
 
110
- it 'should return nil on error' do
111
- cookies[:fridge_session] = 'foobar'
112
- expect(controller.session_token).to be_nil
123
+ it 'should downgrade the token' do
124
+ cookies[:fridge_session] = access_token.serialize
125
+ expect(controller.session_token.scope).to eq 'read'
113
126
  end
114
127
 
115
- it 'should return the token stored in :fridge_session' do
128
+ it 'should not change the validity of a token' do
116
129
  cookies[:fridge_session] = access_token.serialize
117
- expect(controller.session_token.id).to eq access_token.id
130
+ expect(controller.session_token).to be_valid
118
131
  end
119
132
  end
133
+ end
120
134
 
121
- describe '#validate_token' do
122
- it 'should return false if the token is invalid' do
123
- Fridge.configuration.validator = ->(_) { false }
124
- expect(controller.validate_token(access_token)).to be_false
125
- end
135
+ describe '#validate_token' do
136
+ it 'should return false if the token is invalid' do
137
+ Fridge.configuration.validator = ->(_) { false }
138
+ expect(controller.validate_token(access_token)).to be false
139
+ end
126
140
 
127
- it 'should return false if the token validator fails' do
128
- Fridge.configuration.validator = ->(_) { fail 'Foobar' }
129
- expect(controller.validate_token(access_token)).to be_false
130
- end
141
+ it 'should return false if the token validator fails' do
142
+ Fridge.configuration.validator = ->(_) { raise 'Foobar' }
143
+ expect(controller.validate_token(access_token)).to be false
144
+ end
131
145
 
132
- it 'should return the token if valid' do
133
- Fridge.configuration.validator = ->(_) { true }
134
- expect(controller.validate_token(access_token)).to eq access_token
135
- end
146
+ it 'should return the token if valid' do
147
+ Fridge.configuration.validator = ->(_) { true }
148
+ expect(controller.validate_token(access_token)).to eq access_token
136
149
  end
150
+ end
137
151
 
138
- describe '#validate_token' do
139
- it 'should raise an exception if the token is invalid' do
140
- Fridge.configuration.validator = ->(_) { false }
141
- expect { controller.validate_token!(access_token) }.to raise_error
142
- end
152
+ describe '#validate_token' do
153
+ it 'should raise an exception if the token is invalid' do
154
+ Fridge.configuration.validator = ->(_) { false }
155
+ expect { controller.validate_token!(access_token) }
156
+ .to raise_error Fridge::InvalidToken
157
+ end
143
158
 
144
- it 'should return the token if valid' do
145
- Fridge.configuration.validator = ->(_) { true }
146
- expect(controller.validate_token!(access_token)).to eq access_token
147
- end
159
+ it 'should return the token if valid' do
160
+ Fridge.configuration.validator = ->(_) { true }
161
+ expect(controller.validate_token!(access_token)).to eq access_token
148
162
  end
163
+ end
149
164
 
150
- describe '#sessionize_token' do
151
- it 'should set a session cookie' do
152
- Rails.stub_chain(:env, :development?) { false }
153
- controller.sessionize_token(access_token)
154
- expect(cookies[:fridge_session]).to eq access_token.serialize
155
- end
165
+ describe '#sessionize_token' do
166
+ it 'should set a session cookie' do
167
+ Rails.stub_chain(:env, :development?) { false }
168
+ controller.sessionize_token(access_token)
169
+ expect(cookies[:fridge_session]).to eq access_token.serialize
156
170
  end
171
+ end
157
172
 
158
- describe '#fridge_cookie_name' do
159
- it 'is configurable' do
160
- Fridge.configuration.cookie_name = 'foobar'
161
- expect(controller.fridge_cookie_name).to eq 'foobar'
162
- end
173
+ describe '#fridge_cookie_name' do
174
+ it 'is configurable' do
175
+ Fridge.configuration.cookie_name = 'foobar'
176
+ expect(controller.fridge_cookie_name).to eq 'foobar'
163
177
  end
178
+ end
164
179
 
165
- describe '#write_shared_cookie' do
166
- before { Rails.stub_chain(:env, :development?) { false } }
180
+ describe '#write_shared_cookie' do
181
+ before { Rails.stub_chain(:env, :development?) { false } }
167
182
 
168
- it 'should save cookie' do
169
- controller.write_shared_cookie(:organization_url, organization_url)
170
- expect(cookies[:organization_url]).to eq organization_url
171
- end
183
+ it 'should save cookie' do
184
+ controller.write_shared_cookie(:organization_url, organization_url)
185
+ expect(cookies[:organization_url]).to eq organization_url
172
186
  end
187
+ end
173
188
 
174
- describe '#read_shared_cookie' do
175
- it 'should read cookie' do
176
- cookies[:organization_url] = { value: organization_url }
177
- expect(controller.read_shared_cookie(:organization_url)).to(
178
- eq organization_url
179
- )
180
- end
189
+ describe '#read_shared_cookie' do
190
+ it 'should read cookie' do
191
+ cookies[:organization_url] = { value: organization_url }
192
+ expect(controller.read_shared_cookie(:organization_url)).to(
193
+ eq organization_url
194
+ )
181
195
  end
196
+ end
182
197
 
183
- describe '#delete_shared_cookie' do
184
- before { Rails.stub_chain(:env, :development?) { false } }
198
+ describe '#delete_shared_cookie' do
199
+ before { Rails.stub_chain(:env, :development?) { false } }
185
200
 
186
- it 'should delete cookie' do
187
- controller.write_shared_cookie(:organization_url, organization_url)
188
- controller.delete_shared_cookie(:organization_url)
189
- expect(cookies[:organization_url]).to be_nil
190
- end
201
+ it 'should delete cookie' do
202
+ controller.write_shared_cookie(:organization_url, organization_url)
203
+ controller.delete_shared_cookie(:organization_url)
204
+ expect(cookies[:organization_url]).to be_nil
191
205
  end
206
+ end
192
207
 
193
- describe '#fridge_cookie_options' do
194
- before { Rails.stub_chain(:env, :development?) { false } }
208
+ describe '#fridge_cookie_options' do
209
+ before { Rails.stub_chain(:env, :development?) { false } }
195
210
 
196
- it 'are configurable' do
197
- Fridge.configuration.cookie_options = { foobar: true }
198
- options = controller.fridge_cookie_options
199
- expect(options[:domain]).to eq :all
200
- expect(options[:foobar]).to eq true
201
- end
211
+ it 'are configurable' do
212
+ Fridge.configuration.cookie_options = { foobar: true }
213
+ options = controller.fridge_cookie_options
214
+ expect(options[:domain]).to eq :all
215
+ expect(options[:foobar]).to eq true
202
216
  end
203
217
  end
204
218
  end
@@ -1,14 +1,22 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
 
4
+ require 'active_support/all'
5
+ require 'action_controller'
6
+ require 'action_dispatch'
7
+ require 'action_view'
8
+
9
+ require 'fridge'
10
+ require 'fridge/rails_helpers'
11
+
12
+ require 'rspec'
13
+ require 'rspec/rails'
14
+
4
15
  # Load shared spec files
5
16
  Dir["#{File.dirname(__FILE__)}/shared/**/*.rb"].each do |file|
6
17
  require file
7
18
  end
8
19
 
9
- # Require library up front
10
- require 'fridge'
11
-
12
20
  RSpec.configure do |config|
13
21
  config.before { Fridge.configuration.reset }
14
22
  end
metadata CHANGED
@@ -1,139 +1,139 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fridge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Macreery
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-30 00:00:00.000000000 Z
11
+ date: 2020-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_config
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: jwt
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.1.13
33
+ version: 1.5.6
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.1.13
40
+ version: 1.5.6
41
41
  - !ruby/object:Gem::Dependency
42
- name: bundler
42
+ name: aptible-tasks
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '1.5'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '1.5'
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: aptible-tasks
56
+ name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '1.5'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '1.5'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rake
70
+ name: pry
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rails
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: rspec
98
+ name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ~>
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: '2.0'
103
+ version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ~>
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: '2.0'
110
+ version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rspec-rails
112
+ name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '3.0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '3.0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: pry
126
+ name: rspec-rails
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>='
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>='
136
+ - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  description: Token validation for distributed resource servers
@@ -143,9 +143,10 @@ executables: []
143
143
  extensions: []
144
144
  extra_rdoc_files: []
145
145
  files:
146
- - .gitignore
147
- - .rspec
148
- - .travis.yml
146
+ - ".github/CODEOWNERS"
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - ".travis.yml"
149
150
  - Gemfile
150
151
  - LICENSE.md
151
152
  - README.md
@@ -153,13 +154,13 @@ files:
153
154
  - fridge.gemspec
154
155
  - lib/fridge.rb
155
156
  - lib/fridge/access_token.rb
157
+ - lib/fridge/expired_token.rb
156
158
  - lib/fridge/invalid_token.rb
157
159
  - lib/fridge/rails_helpers.rb
158
160
  - lib/fridge/railtie.rb
159
161
  - lib/fridge/serialization_error.rb
160
162
  - lib/fridge/version.rb
161
163
  - spec/fixtures/app.rb
162
- - spec/fixtures/controller.rb
163
164
  - spec/fridge/access_token_spec.rb
164
165
  - spec/fridge/rails_helpers_spec.rb
165
166
  - spec/spec_helper.rb
@@ -167,29 +168,27 @@ homepage: https://github.com/aptible/fridge
167
168
  licenses:
168
169
  - MIT
169
170
  metadata: {}
170
- post_install_message:
171
+ post_install_message:
171
172
  rdoc_options: []
172
173
  require_paths:
173
174
  - lib
174
175
  required_ruby_version: !ruby/object:Gem::Requirement
175
176
  requirements:
176
- - - '>='
177
+ - - ">="
177
178
  - !ruby/object:Gem::Version
178
179
  version: '0'
179
180
  required_rubygems_version: !ruby/object:Gem::Requirement
180
181
  requirements:
181
- - - '>='
182
+ - - ">="
182
183
  - !ruby/object:Gem::Version
183
184
  version: '0'
184
185
  requirements: []
185
- rubyforge_project:
186
- rubygems_version: 2.2.2
187
- signing_key:
186
+ rubygems_version: 3.0.3
187
+ signing_key:
188
188
  specification_version: 4
189
189
  summary: Token validation for distributed resource servers
190
190
  test_files:
191
191
  - spec/fixtures/app.rb
192
- - spec/fixtures/controller.rb
193
192
  - spec/fridge/access_token_spec.rb
194
193
  - spec/fridge/rails_helpers_spec.rb
195
194
  - spec/spec_helper.rb
@@ -1,5 +0,0 @@
1
- require 'fridge/rails_helpers'
2
-
3
- class Controller < ActionController::Base
4
- include Fridge::RailsHelpers
5
- end