fridge 0.1.2 → 0.2.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
  SHA1:
3
- metadata.gz: e218e44c99f35477998c66a5f0c78bc81d31a4eb
4
- data.tar.gz: 884d82c5dfc0c5dfe1a2efb43a7a5accf3e0d2b5
3
+ metadata.gz: b49455bd0f488a16a7644a83d79f3c4cbb5d71b6
4
+ data.tar.gz: c778c54e88438ef63194d90304860710026bc403
5
5
  SHA512:
6
- metadata.gz: c0fd5108ef1b8e9a80cf79f918d3091cc3e352ff3d279c90bd6d857e4aedc7a66065e2eee88558e066d871796090146e213b0eeb34f5c5b8262204ce5068d1b0
7
- data.tar.gz: 5b6e2a02c965a70d653174ad65eb2e2c436a29071cd2abebcd718b08a435afa9a6a4a6200697debedf5db02e5b1105da33fcd970dbe081055666af25fc6f5da3
6
+ metadata.gz: 9cea20d8b86972656d086f046ddc8d0248215116200a3bbf2bb5b2b916919bd973b90bc8781325ffbb51e36079ad77396711508c44824ec252a76ae2223211c9
7
+ data.tar.gz: 7d12fc628282bc7fb2910b0148c55e0a98186ca423b6bf34c2bea4ae8f33e59b5ee89df0755ce7c1c46ba8869b3bee9e368de09f3e06117fd02befc38c130c8b
@@ -2,7 +2,8 @@ require 'jwt'
2
2
 
3
3
  module Fridge
4
4
  class AccessToken
5
- attr_accessor :id, :issuer, :subject, :scope, :expires_at, :jwt
5
+ attr_accessor :id, :issuer, :subject, :scope, :expires_at,
6
+ :jwt, :attributes
6
7
 
7
8
  # rubocop:disable MethodLength
8
9
  def initialize(jwt_or_options = nil)
@@ -14,9 +15,11 @@ module Fridge
14
15
  when Hash then jwt_or_options
15
16
  else {}
16
17
  end
17
- options.each do |key, value|
18
- instance_variable_set("@#{key}", value)
18
+ [:id, :issuer, :subject, :scope, :expires_at].each do |key|
19
+ send "#{key}=", options.delete(key)
19
20
  end
21
+ self.attributes = options.reject { |k, v| v.nil? }
22
+ attributes.symbolize_keys!
20
23
  end
21
24
  # rubocop:enable MethodLength
22
25
 
@@ -38,23 +41,26 @@ module Fridge
38
41
  sub: subject,
39
42
  scope: scope,
40
43
  exp: expires_at.to_i
41
- }, private_key, algorithm)
44
+ }.merge(attributes), private_key, algorithm)
42
45
  rescue
43
46
  raise SerializationError, 'Invalid private key or signing algorithm'
44
47
  end
45
48
 
49
+ # rubocop:disable MethodLength
46
50
  def decode_and_verify(jwt)
47
51
  hash = JWT.decode(jwt, public_key)
48
- {
49
- id: hash['id'],
50
- issuer: hash['iss'],
51
- subject: hash['sub'],
52
- scope: hash['scope'],
53
- expires_at: Time.at(hash['exp'])
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'))
54
58
  }
55
- rescue JWT::DecodeError
56
- raise InvalidToken, 'Invalid access token'
59
+ base.merge(hash)
60
+ rescue JWT::DecodeError
61
+ raise InvalidToken, 'Invalid access token'
57
62
  end
63
+ # rubocop:enable MethodLength
58
64
 
59
65
  def valid?
60
66
  !expired?
@@ -91,6 +97,14 @@ module Fridge
91
97
 
92
98
  protected
93
99
 
100
+ def method_missing(method, *args, &block)
101
+ if attributes.key?(method)
102
+ attributes[method]
103
+ else
104
+ super
105
+ end
106
+ end
107
+
94
108
  def validate_parameters!
95
109
  [:subject, :expires_at].each do |attribute|
96
110
  unless send(attribute)
@@ -25,39 +25,64 @@ module Fridge
25
25
  end
26
26
 
27
27
  def session_token
28
- return unless cookies[:session_token]
29
- @session_token = AccessToken.new(cookies[:session_token]).tap do |token|
28
+ return unless session_cookie
29
+ @session_token ||= AccessToken.new(session_cookie).tap do |token|
30
30
  validate_token!(token)
31
31
  end
32
32
  rescue
33
- clear_session_token
34
- @session_token = nil
33
+ clear_session_cookie
35
34
  end
36
35
 
36
+ # Validates token, and returns the token, or nil
37
+ def validate_token(access_token)
38
+ validator = Fridge.configuration.validator
39
+ validator.call(access_token) && access_token
40
+ rescue
41
+ false
42
+ end
43
+
44
+ # Validates token, and raises an exception if invalid
37
45
  def validate_token!(access_token)
38
46
  validator = Fridge.configuration.validator
39
- fail InvalidToken unless validator.call(access_token)
47
+ if validator.call(access_token)
48
+ access_token
49
+ else
50
+ fail InvalidToken
51
+ end
40
52
  end
41
53
 
42
- def store_session_token(access_token)
54
+ def sessionize_token(access_token)
43
55
  # Ensure that any cookie-persisted tokens are read-only
44
56
  access_token.scope = 'read'
45
57
 
46
58
  jwt = access_token.serialize
47
- cookies[:session_token] = cookie_options.merge(
59
+ self.session_cookie = {
48
60
  value: jwt,
49
- expires_at: access_token.expires_at
50
- )
61
+ expires: access_token.expires_at
62
+ }.merge(fridge_cookie_options)
51
63
  end
52
64
 
53
- def clear_session_token
54
- cookies.delete :session_token, domain: :all
65
+ def session_cookie
66
+ cookies[fridge_cookie_name]
67
+ end
68
+
69
+ def session_cookie=(cookie)
70
+ cookies[fridge_cookie_name] = cookie
71
+ end
72
+
73
+ def clear_session_cookie
74
+ cookies.delete fridge_cookie_name, domain: :all
55
75
  nil
56
76
  end
57
77
 
58
- def cookie_options
78
+ def fridge_cookie_name
79
+ Fridge.configuration.cookie_name
80
+ end
81
+
82
+ def fridge_cookie_options
59
83
  secure = !Rails.env.development?
60
- { domain: :all, secure: secure, httponly: true }
84
+ options = { domain: :all, secure: secure, httponly: true }
85
+ options.merge(Fridge.configuration.cookie_options)
61
86
  end
62
87
  end
63
88
  end
@@ -1,3 +1,3 @@
1
1
  module Fridge
2
- VERSION = '0.1.2'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/fridge.rb CHANGED
@@ -19,5 +19,8 @@ module Fridge
19
19
  # A validator must raise an exception or return a false value for an
20
20
  # invalid token
21
21
  has :validator, classes: [Proc], default: ->(token) { token.valid? }
22
+
23
+ has :cookie_name, classes: [String, Symbol], default: :fridge_session
24
+ has :cookie_options, classes: [Hash], default: {}
22
25
  end
23
26
  end
@@ -32,7 +32,7 @@ describe Fridge::AccessToken do
32
32
  let(:options) do
33
33
  {
34
34
  id: SecureRandom.uuid,
35
- iss: 'https://auth.aptible.com',
35
+ issuer: 'https://auth.aptible.com',
36
36
  subject: "https://auth.aptible.com/users/#{SecureRandom.uuid}",
37
37
  scope: 'read',
38
38
  expires_at: Time.now + 3600
@@ -86,6 +86,14 @@ describe Fridge::AccessToken do
86
86
  expect(copy.scope).to eq subject.scope
87
87
  end
88
88
 
89
+ it 'should include custom attributes' do
90
+ subject = described_class.new(options.merge(foo: 'bar'))
91
+ copy = described_class.new(subject.serialize)
92
+
93
+ expect(copy.attributes[:foo]).to eq 'bar'
94
+ expect(copy.foo).to eq 'bar'
95
+ end
96
+
89
97
  it 'should raise an error if required attributes are missing' do
90
98
  subject.subject = nil
91
99
  expect { subject.serialize }.to raise_error Fridge::SerializationError
@@ -99,27 +99,74 @@ describe Controller, type: :controller do
99
99
 
100
100
  describe '#session_token' do
101
101
  it 'should delete all cookies on error' do
102
- cookies[:session_token] = 'foobar'
102
+ cookies[:fridge_session] = 'foobar'
103
103
  controller.session_token
104
- expect(cookies.deleted?(:session_token, domain: :all)).to be_true
104
+ expect(cookies.deleted?(:fridge_session, domain: :all)).to be_true
105
105
  end
106
106
 
107
107
  it 'should return nil on error' do
108
- cookies[:session_token] = 'foobar'
108
+ cookies[:fridge_session] = 'foobar'
109
109
  expect(controller.session_token).to be_nil
110
110
  end
111
111
 
112
- it 'should return the token stored in :session_token' do
113
- cookies[:session_token] = access_token.serialize
112
+ it 'should return the token stored in :fridge_session' do
113
+ cookies[:fridge_session] = access_token.serialize
114
114
  expect(controller.session_token.id).to eq access_token.id
115
115
  end
116
116
  end
117
117
 
118
- describe '#store_session_token' do
118
+ describe '#validate_token' do
119
+ it 'should return false if the token is invalid' do
120
+ Fridge.configuration.validator = ->(token) { false }
121
+ expect(controller.validate_token(access_token)).to be_false
122
+ end
123
+
124
+ it 'should return false if the token validator fails' do
125
+ Fridge.configuration.validator = ->(token) { fail 'Foobar' }
126
+ expect(controller.validate_token(access_token)).to be_false
127
+ end
128
+
129
+ it 'should return the token if valid' do
130
+ Fridge.configuration.validator = ->(token) { true }
131
+ expect(controller.validate_token(access_token)).to eq access_token
132
+ end
133
+ end
134
+
135
+ describe '#validate_token' do
136
+ it 'should raise an exception if the token is invalid' do
137
+ Fridge.configuration.validator = ->(token) { false }
138
+ expect { controller.validate_token!(access_token) }.to raise_error
139
+ end
140
+
141
+ it 'should return the token if valid' do
142
+ Fridge.configuration.validator = ->(token) { true }
143
+ expect(controller.validate_token!(access_token)).to eq access_token
144
+ end
145
+ end
146
+
147
+ describe '#sessionize_token' do
119
148
  it 'should set a session cookie' do
120
149
  Rails.stub_chain(:env, :development?) { false }
121
- controller.store_session_token(access_token)
122
- expect(cookies[:session_token]).to eq access_token.serialize
150
+ controller.sessionize_token(access_token)
151
+ expect(cookies[:fridge_session]).to eq access_token.serialize
152
+ end
153
+ end
154
+
155
+ describe '#fridge_cookie_name' do
156
+ it 'is configurable' do
157
+ Fridge.configuration.cookie_name = 'foobar'
158
+ expect(controller.fridge_cookie_name).to eq 'foobar'
159
+ end
160
+ end
161
+
162
+ describe '#fridge_cookie_options' do
163
+ before { Rails.stub_chain(:env, :development?) { false } }
164
+
165
+ it 'are configurable' do
166
+ Fridge.configuration.cookie_options = { foobar: true }
167
+ options = controller.fridge_cookie_options
168
+ expect(options[:domain]).to eq :all
169
+ expect(options[:foobar]).to eq true
123
170
  end
124
171
  end
125
172
  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.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Macreery
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-11 00:00:00.000000000 Z
11
+ date: 2014-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_config