fridge 0.1.2 → 0.2.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
  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