fridge 0.3.0 → 0.4.3

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: f4a824a32d9980601cfa696083b4a7c2765f26e0
4
- data.tar.gz: 27f1e343ab6fdd60a947254f3c9eb428370cb11e
2
+ SHA256:
3
+ metadata.gz: c01604ddabbbd9a954e9fe73e1567aa0232509c30ed09e7694315131e0402abf
4
+ data.tar.gz: fd4199b0194b7a63e7062c630dc9bb58c75eab607e27ebf13d24fe001a654c40
5
5
  SHA512:
6
- metadata.gz: b7f135652cd8d9702f9fd3f5ed32f9b6b31ba702ef107a18f32b73303200b89302659991a666c98f432cb9cb5bc2109444b88f9239e3781dd9378c738cc05567
7
- data.tar.gz: 446fb0d2f82514a9d978159f699fc1f031948ad48c0364b46bae54d285c700fc84f86b6c6d2b6a126fef340f51dd97fdb07a36b250df0018c7f3350b390552fc
6
+ metadata.gz: 2df7422238fac73bb4263af3af697d049b8ae870ed4c1610c40fdde3bcfd422b0cf8ac5f92a3889201b2aec5d222cda04fc49f5ee1797f6a0a2e3ea615094cb7
7
+ data.tar.gz: e11293fdad80f5a7dfa6f6538b244f67ed59fc8e9867dde34c49c1067555936881b4d7b0de9f0ab5910a2a57b6d68dec0bd76462c888f7531c12ccdd6beb5d47
@@ -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,6 +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) and contributors.
84
-
85
- [<img src="https://s.gravatar.com/avatar/f7790b867ae619ae0496460aa28c5861?s=60" style="border-radius: 50%;" alt="@fancyremarker" />](https://github.com/fancyremarker)
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,32 @@ 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
62
55
  end
63
- # rubocop:enable MethodLength
64
56
 
65
57
  def downgrade
66
58
  self.scope = 'read'
@@ -76,8 +68,9 @@ module Fridge
76
68
 
77
69
  def private_key
78
70
  return unless config.private_key
71
+
79
72
  @private_key ||= OpenSSL::PKey::RSA.new(config.private_key)
80
- rescue
73
+ rescue StandardError
81
74
  nil
82
75
  end
83
76
 
@@ -87,7 +80,7 @@ module Fridge
87
80
  elsif config.public_key
88
81
  @public_key ||= OpenSSL::PKey::RSA.new(config.public_key)
89
82
  end
90
- rescue
83
+ rescue StandardError
91
84
  nil
92
85
  end
93
86
 
@@ -109,19 +102,72 @@ module Fridge
109
102
  end
110
103
  end
111
104
 
105
+ def respond_to_missing?(method, include_private = false)
106
+ attributes.key?(method) || super
107
+ end
108
+
112
109
  def validate_parameters!
113
110
  [:subject, :expires_at].each do |attribute|
114
111
  next if send(attribute)
115
- fail SerializationError, "Missing attribute: #{attribute}"
112
+
113
+ raise SerializationError, "Missing attribute: #{attribute}"
116
114
  end
117
115
  end
118
116
 
119
117
  def validate_private_key!
120
- fail SerializationError, 'No private key configured' unless private_key
118
+ raise SerializationError, 'No private key configured' unless private_key
121
119
  end
122
120
 
123
121
  def validate_public_key!
124
- 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
125
171
  end
126
172
  end
127
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
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
 
@@ -78,12 +88,12 @@ module Fridge
78
88
  end
79
89
 
80
90
  def clear_session_cookie
81
- cookies.delete fridge_cookie_name, domain: :all
91
+ cookies.delete fridge_cookie_name, domain: auth_domain
82
92
  nil
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)
@@ -110,8 +121,14 @@ module Fridge
110
121
 
111
122
  def fridge_cookie_options
112
123
  secure = !Rails.env.development?
113
- options = { domain: :all, secure: secure, httponly: true }
124
+ options = { domain: auth_domain, secure: secure, httponly: true }
114
125
  options.merge(Fridge.configuration.cookie_options)
115
126
  end
127
+
128
+ def auth_domain
129
+ Aptible::Auth.configuration.root_url.sub(%r{^https?://}, '')
130
+ rescue StandardError
131
+ 'auth.aptible.com'
132
+ end
116
133
  end
117
134
  end
@@ -1,3 +1,3 @@
1
1
  module Fridge
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.3'.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
@@ -1,218 +1,219 @@
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}"
11
- end
12
- let(:private_key) { OpenSSL::PKey::RSA.new(1024) }
13
- let(:public_key) { OpenSSL::PKey::RSA.new(private_key.public_key) }
4
+ describe Fridge::RailsHelpers do
5
+ include RSpec::Rails::ControllerExampleGroup
14
6
 
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) }
7
+ controller(ActionController::Base) { include Fridge::RailsHelpers }
22
8
 
23
- let(:cookies) { controller.send(:cookies) }
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) }
24
22
 
25
- before { Fridge.configuration.private_key = private_key.to_s }
26
- before { Fridge.configuration.public_key = public_key.to_s }
23
+ let(:cookies) { controller.send(:cookies) }
27
24
 
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
25
+ before { Fridge.configuration.private_key = private_key.to_s }
26
+ before { Fridge.configuration.public_key = public_key.to_s }
33
27
 
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
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'
38
32
  end
39
33
 
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
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
38
+ end
45
39
 
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
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
50
44
  end
51
45
 
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
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
57
51
 
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
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
62
56
  end
63
57
 
64
- describe '#current_token' do
65
- before { controller.stub(:bearer_token) { access_token.serialize } }
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
62
+ end
66
63
 
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
64
+ describe '#current_token' do
65
+ before { controller.stub(:bearer_token) { access_token.serialize } }
71
66
 
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
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
76
71
 
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
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
81
76
 
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
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
85
81
 
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
82
+ it 'should not raise an error if a valid token is passed' do
83
+ expect { controller.current_token }.not_to raise_error
89
84
  end
90
85
 
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
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
96
90
 
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
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
101
95
  end
102
96
 
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
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
109
102
 
110
- it 'should return nil on error' do
111
- cookies[:fridge_session] = 'foobar'
112
- expect(controller.session_token).to be_nil
113
- 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: 'auth.aptible.com'))
108
+ .to be true
109
+ end
114
110
 
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
118
- end
111
+ it 'should return nil on error' do
112
+ cookies[:fridge_session] = 'foobar'
113
+ expect(controller.session_token).to be_nil
114
+ end
119
115
 
120
- context 'with a non-:read scope' do
121
- before { options.merge!(scope: 'manage') }
116
+ it 'should return the token stored in :fridge_session' do
117
+ cookies[:fridge_session] = access_token.serialize
118
+ expect(controller.session_token.id).to eq access_token.id
119
+ end
122
120
 
123
- it 'should downgrade the token' do
124
- cookies[:fridge_session] = access_token.serialize
125
- expect(controller.session_token.scope).to eq 'read'
126
- end
121
+ context 'with a non-:read scope' do
122
+ before { options.merge!(scope: 'manage') }
127
123
 
128
- it 'should not change the validity of a token' do
129
- cookies[:fridge_session] = access_token.serialize
130
- expect(controller.session_token).to be_valid
131
- end
124
+ it 'should downgrade the token' do
125
+ cookies[:fridge_session] = access_token.serialize
126
+ expect(controller.session_token.scope).to eq 'read'
132
127
  end
133
- end
134
128
 
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
129
+ it 'should not change the validity of a token' do
130
+ cookies[:fridge_session] = access_token.serialize
131
+ expect(controller.session_token).to be_valid
139
132
  end
133
+ end
134
+ end
140
135
 
141
- it 'should return false if the token validator fails' do
142
- Fridge.configuration.validator = ->(_) { fail 'Foobar' }
143
- expect(controller.validate_token(access_token)).to be_false
144
- end
136
+ describe '#validate_token' do
137
+ it 'should return false if the token is invalid' do
138
+ Fridge.configuration.validator = ->(_) { false }
139
+ expect(controller.validate_token(access_token)).to be false
140
+ end
145
141
 
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
149
- end
142
+ it 'should return false if the token validator fails' do
143
+ Fridge.configuration.validator = ->(_) { raise 'Foobar' }
144
+ expect(controller.validate_token(access_token)).to be false
150
145
  end
151
146
 
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) }.to raise_error
156
- end
147
+ it 'should return the token if valid' do
148
+ Fridge.configuration.validator = ->(_) { true }
149
+ expect(controller.validate_token(access_token)).to eq access_token
150
+ end
151
+ end
157
152
 
158
- it 'should return the token if valid' do
159
- Fridge.configuration.validator = ->(_) { true }
160
- expect(controller.validate_token!(access_token)).to eq access_token
161
- end
153
+ describe '#validate_token' do
154
+ it 'should raise an exception if the token is invalid' do
155
+ Fridge.configuration.validator = ->(_) { false }
156
+ expect { controller.validate_token!(access_token) }
157
+ .to raise_error Fridge::InvalidToken
162
158
  end
163
159
 
164
- describe '#sessionize_token' do
165
- it 'should set a session cookie' do
166
- Rails.stub_chain(:env, :development?) { false }
167
- controller.sessionize_token(access_token)
168
- expect(cookies[:fridge_session]).to eq access_token.serialize
169
- end
160
+ it 'should return the token if valid' do
161
+ Fridge.configuration.validator = ->(_) { true }
162
+ expect(controller.validate_token!(access_token)).to eq access_token
170
163
  end
164
+ end
171
165
 
172
- describe '#fridge_cookie_name' do
173
- it 'is configurable' do
174
- Fridge.configuration.cookie_name = 'foobar'
175
- expect(controller.fridge_cookie_name).to eq 'foobar'
176
- end
166
+ describe '#sessionize_token' do
167
+ it 'should set a session cookie' do
168
+ Rails.stub_chain(:env, :development?) { false }
169
+ controller.sessionize_token(access_token)
170
+ expect(cookies[:fridge_session]).to eq access_token.serialize
177
171
  end
172
+ end
178
173
 
179
- describe '#write_shared_cookie' do
180
- before { Rails.stub_chain(:env, :development?) { false } }
174
+ describe '#fridge_cookie_name' do
175
+ it 'is configurable' do
176
+ Fridge.configuration.cookie_name = 'foobar'
177
+ expect(controller.fridge_cookie_name).to eq 'foobar'
178
+ end
179
+ end
181
180
 
182
- it 'should save cookie' do
183
- controller.write_shared_cookie(:organization_url, organization_url)
184
- expect(cookies[:organization_url]).to eq organization_url
185
- end
181
+ describe '#write_shared_cookie' do
182
+ before { Rails.stub_chain(:env, :development?) { false } }
183
+
184
+ it 'should save cookie' do
185
+ controller.write_shared_cookie(:organization_url, organization_url)
186
+ expect(cookies[:organization_url]).to eq organization_url
186
187
  end
188
+ end
187
189
 
188
- describe '#read_shared_cookie' do
189
- it 'should read cookie' do
190
- cookies[:organization_url] = { value: organization_url }
191
- expect(controller.read_shared_cookie(:organization_url)).to(
192
- eq organization_url
193
- )
194
- end
190
+ describe '#read_shared_cookie' do
191
+ it 'should read cookie' do
192
+ cookies[:organization_url] = { value: organization_url }
193
+ expect(controller.read_shared_cookie(:organization_url)).to(
194
+ eq organization_url
195
+ )
195
196
  end
197
+ end
196
198
 
197
- describe '#delete_shared_cookie' do
198
- before { Rails.stub_chain(:env, :development?) { false } }
199
+ describe '#delete_shared_cookie' do
200
+ before { Rails.stub_chain(:env, :development?) { false } }
199
201
 
200
- it 'should delete cookie' do
201
- controller.write_shared_cookie(:organization_url, organization_url)
202
- controller.delete_shared_cookie(:organization_url)
203
- expect(cookies[:organization_url]).to be_nil
204
- end
202
+ it 'should delete cookie' do
203
+ controller.write_shared_cookie(:organization_url, organization_url)
204
+ controller.delete_shared_cookie(:organization_url)
205
+ expect(cookies[:organization_url]).to be_nil
205
206
  end
207
+ end
206
208
 
207
- describe '#fridge_cookie_options' do
208
- before { Rails.stub_chain(:env, :development?) { false } }
209
+ describe '#fridge_cookie_options' do
210
+ before { Rails.stub_chain(:env, :development?) { false } }
209
211
 
210
- it 'are configurable' do
211
- Fridge.configuration.cookie_options = { foobar: true }
212
- options = controller.fridge_cookie_options
213
- expect(options[:domain]).to eq :all
214
- expect(options[:foobar]).to eq true
215
- end
212
+ it 'are configurable' do
213
+ Fridge.configuration.cookie_options = { foobar: true }
214
+ options = controller.fridge_cookie_options
215
+ expect(options[:domain]).to eq 'auth.aptible.com'
216
+ expect(options[:foobar]).to eq true
216
217
  end
217
218
  end
218
219
  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,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fridge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.3
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: 2015-04-01 00:00:00.000000000 Z
11
+ date: 2021-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_config
@@ -30,14 +30,28 @@ dependencies:
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
+ - !ruby/object:Gem::Dependency
42
+ name: aptible-tasks
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -53,7 +67,7 @@ dependencies:
53
67
  - !ruby/object:Gem::Version
54
68
  version: '1.5'
55
69
  - !ruby/object:Gem::Dependency
56
- name: aptible-tasks
70
+ name: pry
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
@@ -67,7 +81,7 @@ dependencies:
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
- name: rake
84
+ name: rails
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - ">="
@@ -81,7 +95,7 @@ dependencies:
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
- name: rails
98
+ name: rake
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - ">="
@@ -100,14 +114,14 @@ dependencies:
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: '2.0'
117
+ version: '3.0'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: '2.0'
124
+ version: '3.0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: rspec-rails
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -122,20 +136,6 @@ dependencies:
122
136
  - - ">="
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: pry
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
139
  description: Token validation for distributed resource servers
140
140
  email:
141
141
  - frank@macreery.com
@@ -143,6 +143,7 @@ executables: []
143
143
  extensions: []
144
144
  extra_rdoc_files: []
145
145
  files:
146
+ - ".github/CODEOWNERS"
146
147
  - ".gitignore"
147
148
  - ".rspec"
148
149
  - ".travis.yml"
@@ -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,7 +168,7 @@ 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
@@ -182,14 +183,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
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