firebase_id_token 2.3.2 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04e416cf72a26dfef4ba1555005cce301af06b10d68c34cb31873e4de4204307
4
- data.tar.gz: b35dbae1fcb4f1da7e6a240be49662ec090e70f22e9e940a2173583c35a3e91b
3
+ metadata.gz: eef2d227ba8e21f033a7d4c68f7d973a6d25b26e1c1900f43784606f1020332c
4
+ data.tar.gz: 2899b73b48998f8e14337eada01a76980e02fd1994821afd8a902f23ec40dfd5
5
5
  SHA512:
6
- metadata.gz: 59a99e199abc3b4280500cc6202b78d125cb89874c7e4c0fc19956c25f89362ec8262af785fcfd1efd38c8a429dc5a231c6cca39b0a170c007cf7d2962c84429
7
- data.tar.gz: c3654c443865086ba7aaaa66a5851ea6cf6549fc590ae24055491c0b44619a22399ea148d34e7e245dd5fc7ccf0bad0e04a2c3a3d1746ba1b40088db212e8f0b
6
+ metadata.gz: 7f64121a625def6dd48f7090fd5bfe25ed3ca754510a993b3dc9124b865e92c5610010a156c5520359c9c93d7301e8dfe9c4a46630f99df50b84742a61129fbf
7
+ data.tar.gz: 6b0fd92129b034f482fe8ed910a23e9f7201d42d510b03100f974e7adc919d9125915885c5211cf1c1cbf42363c72a987e3a1b493047aec27193317e2569d4f8
@@ -1,7 +1,7 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.4.0
5
- before_install: gem install bundler -v 1.14.6
4
+ - 2.6.3
5
+ before_install: gem install bundler -v 1.17.2
6
6
  services:
7
7
  - redis-server
@@ -0,0 +1,105 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ### Fixed
10
+ - Rake development dependency vulnerability [CVE-2020-8130](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-8130).
11
+
12
+ ### Changed
13
+ - Using Bundler 1.17.2.
14
+
15
+ ### Added
16
+ - Ability to raise errors when verifying tokens.
17
+ - `FirebaseIdToken::Certificates.find!` method.
18
+ - `FirebaseIdToken::Signatures.verify!` method.
19
+ - `FirebaseIdToken::Exceptions::CertificateNotFound` exception.
20
+ - `:raise_error` option to `FirebaseIdToken::Signature.verify`.
21
+ - `CHANGELOG.md` file.
22
+
23
+ ## [2.3.2] - 2020-02-15
24
+
25
+ ### Fixed
26
+ - Certificate fixture not accessible when packing Gem into Rails application.
27
+
28
+ ### Changed
29
+ - Bumped Bundler version to 1.14.
30
+
31
+ ## [2.3.1] - 2019-08-13
32
+
33
+ ### Fixed
34
+ - Certificate fixture reading issue.
35
+
36
+ ### Added
37
+ - Test mode.
38
+ - Test mode documentation.
39
+
40
+ ## [2.3.0] - 2018-06-18
41
+
42
+ ### Changed
43
+ - Started to use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
44
+ - Runtime dependencies versions upgraded.
45
+ - Use Redis `>= 3.3.3`.
46
+
47
+ ## [2.2.0] - 2018-05-21
48
+ *Nothing tracked, release skipped.*
49
+
50
+ ## [2.1.0] - 2018-04-09
51
+
52
+ ### Fixed
53
+ - `FirebaseIdToken::Signature.verify` now returns `nil` for newly issued tokens.
54
+
55
+ ## [2.0.0] - 2017-12-09
56
+
57
+ ### Fixed
58
+ - Typo on Rake task `force_request` name.
59
+
60
+ ## [1.3.0] - 2017-09-15
61
+
62
+ ### Changed
63
+ - Renamed `Certificates.request_anyway` to `Certificates.request!` (`Certificates.request_anyway` was kept for backwards compatibility.
64
+
65
+ ### Fixed
66
+ - Documentaiton typos.
67
+ - Initializer typos.
68
+
69
+ ## [1.2.2] - 2017-04-29
70
+
71
+ ### Changed
72
+ - Recommended people to use cron tasks instead of background jobs.
73
+ - Set certificates TTL based on cache-control's max-age.
74
+ - Documentation now warns about request during application start in Rails.
75
+
76
+ ### Fixed
77
+ - Documentation typos.
78
+
79
+ ## [1.2.1] - 2017-04-27
80
+
81
+ ### Changed
82
+ - Small improvements on documentation.
83
+
84
+ ## [1.2.0] - 2017-04-26
85
+
86
+ ### Changed
87
+ - The Gem was marked as "ready to use".
88
+
89
+ ## [1.1.0] - 2017-04-26
90
+ *Nothing tracked.*
91
+
92
+ ## [1.0.0] - 2017-04-26
93
+ *Version removed.*
94
+
95
+ ## [0.1.0] - 2017-04-23
96
+ *Version removed.*
97
+
98
+ [2.3.2]: https://github.com/fschuindt/firebase_id_token/compare/2.3.1...2.3.2
99
+ [2.3.1]: https://github.com/fschuindt/firebase_id_token/compare/2.3.0...2.3.1
100
+ [2.3.0]: https://github.com/fschuindt/firebase_id_token/compare/2.0.0...2.3.0
101
+ [2.1.0]: https://github.com/fschuindt/firebase_id_token/compare/2.0.0...2.1.0
102
+ [2.0.0]: https://github.com/fschuindt/firebase_id_token/compare/1.3.0...2.0.0
103
+ [1.3.0]: https://github.com/fschuindt/firebase_id_token/compare/1.2.2...1.3.0
104
+ [1.2.2]: https://github.com/fschuindt/firebase_id_token/compare/1.2.1...1.2.2
105
+ [1.2.1]: https://github.com/fschuindt/firebase_id_token/compare/1.2.0...1.2.1
data/README.md CHANGED
@@ -29,7 +29,7 @@ gem install firebase_id_token
29
29
 
30
30
  or in your Gemfile
31
31
  ```
32
- gem 'firebase_id_token', '~> 2.3.1'
32
+ gem 'firebase_id_token', '~> 2.4.0'
33
33
  ```
34
34
  then
35
35
  ```
@@ -0,0 +1,9 @@
1
+ version: '3'
2
+
3
+ services:
4
+ redis:
5
+ image: redis:5-alpine
6
+ ports:
7
+ - "6379:6379"
8
+ expose:
9
+ - 6379
@@ -22,8 +22,8 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ['lib']
24
24
 
25
- spec.add_development_dependency 'bundler'
26
- spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'bundler', '~> 1.17', '>= 1.17.2'
26
+ spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.3'
27
27
  spec.add_development_dependency 'rspec', '~> 3.0'
28
28
  spec.add_development_dependency 'redcarpet', '~> 3.4', '>= 3.4.0'
29
29
  spec.add_development_dependency 'simplecov', '~> 0.14.1'
@@ -7,6 +7,7 @@ require 'firebase_id_token/version'
7
7
  require 'firebase_id_token/exceptions/no_certificates_error'
8
8
  require 'firebase_id_token/exceptions/certificates_request_error'
9
9
  require 'firebase_id_token/exceptions/certificates_ttl_error'
10
+ require 'firebase_id_token/exceptions/certificate_not_found'
10
11
  require 'firebase_id_token/configuration'
11
12
  require 'firebase_id_token/certificates'
12
13
  require 'firebase_id_token/signature'
@@ -49,7 +50,7 @@ module FirebaseIdToken
49
50
 
50
51
  def self.configuration
51
52
  @configuration ||= Configuration.new
52
- end
53
+ end
53
54
 
54
55
  # Resets Configuration to defaults.
55
56
  def self.reset
@@ -111,13 +111,34 @@ module FirebaseIdToken
111
111
  # FirebaseIdToken::Certificates.request
112
112
  # cert = FirebaseIdToken::Certificates.find "1d6d01f4w7d54c7[...]"
113
113
  # #=> <OpenSSL::X509::Certificate: subject=#<OpenSSL [...]
114
- def self.find(kid)
114
+ def self.find(kid, raise_error: false)
115
115
  certs = new.local_certs
116
116
  raise Exceptions::NoCertificatesError if certs.empty?
117
117
 
118
- if certs[kid]
119
- OpenSSL::X509::Certificate.new certs[kid]
120
- end
118
+ return OpenSSL::X509::Certificate.new certs[kid] if certs[kid]
119
+
120
+ return unless raise_error
121
+
122
+ raise Exceptions::CertificateNotFound,
123
+ "Unable to find a certificate with `#{kid}`."
124
+ end
125
+
126
+ # Returns a `OpenSSL::X509::Certificate` object of the requested Key ID
127
+ # (KID) if there's one.
128
+ #
129
+ # @raise {Exceptions::CertificateNotFound} if it cannot be found.
130
+ #
131
+ # @raise {Exceptions::NoCertificatesError} if the Redis certificates
132
+ # database is empty.
133
+ #
134
+ # @param [String] kid Key ID
135
+ # @return [OpenSSL::X509::Certificate]
136
+ # @example
137
+ # FirebaseIdToken::Certificates.request
138
+ # cert = FirebaseIdToken::Certificates.find! "1d6d01f4w7d54c7[...]"
139
+ # #=> <OpenSSL::X509::Certificate: subject=#<OpenSSL [...]
140
+ def self.find!(kid)
141
+ find(kid, raise_error: true)
121
142
  end
122
143
 
123
144
  # Returns the current certificates TTL (Time-To-Live) in seconds. *Zero
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FirebaseIdToken
4
+ module Exceptions
5
+ # @see FirebaseIdToken::Certificates.find!
6
+ class CertificateNotFound < StandardError; end
7
+ end
8
+ end
@@ -42,9 +42,25 @@ module FirebaseIdToken
42
42
  # Note that it will raise a {Exceptions::NoCertificatesError} if the Redis
43
43
  # certificates database is empty. Ensure to call {Certificates.request}
44
44
  # before, ideally in a background job if you are using Rails.
45
+ #
46
+ # If you would like this to raise and error, rather than silently failing,
47
+ # you can with the `raise_error` parameter. Example:
48
+ #
49
+ # FirebaseIdToken::Signature
50
+ # .verify(token, raise_error: Rails.env.development?)
51
+ #
52
+ # @param raise_error [Boolean] default: false
45
53
  # @return [nil, Hash]
46
- def self.verify(jwt_token)
47
- new(jwt_token).verify
54
+ def self.verify(jwt_token, raise_error: false)
55
+ new(jwt_token, raise_error: raise_error).verify
56
+ end
57
+
58
+ # Equivalent to `.verify(jwt_token, raise_error: true)`.
59
+ #
60
+ # @see {Signature.verify}
61
+ # @return [Hash]
62
+ def self.verify!(jwt_token)
63
+ new(jwt_token, raise_error: true).verify
48
64
  end
49
65
 
50
66
  attr_accessor :firebase_id_token_certificates
@@ -52,21 +68,21 @@ module FirebaseIdToken
52
68
  # Loads attributes: `:project_ids` from {FirebaseIdToken::Configuration},
53
69
  # and `:kid`, `:jwt_token` from the related `jwt_token`.
54
70
  # @param [String] jwt_token Firebase ID Token
55
- def initialize(jwt_token)
71
+ def initialize(jwt_token, raise_error: false)
72
+ @raise_error = raise_error
56
73
  @project_ids = FirebaseIdToken.configuration.project_ids
57
74
  @kid = extract_kid(jwt_token)
58
75
  @jwt_token = jwt_token
59
76
  @firebase_id_token_certificates = FirebaseIdToken.configuration.certificates
60
-
61
77
  end
62
78
 
63
79
  # @see Signature.verify
64
80
  def verify
65
- certificate = firebase_id_token_certificates.find(@kid)
66
- if certificate
67
- payload = decode_jwt_payload(@jwt_token, certificate.public_key)
68
- authorize payload
69
- end
81
+ certificate = firebase_id_token_certificates.find(@kid, raise_error: @raise_error)
82
+ return unless certificate
83
+
84
+ payload = decode_jwt_payload(@jwt_token, certificate.public_key)
85
+ authorize payload
70
86
  end
71
87
 
72
88
  private
@@ -74,13 +90,17 @@ module FirebaseIdToken
74
90
  def extract_kid(jwt_token)
75
91
  JWT.decode(jwt_token, nil, false).last['kid']
76
92
  rescue StandardError
77
- 'none'
93
+ return 'none' unless @raise_error
94
+
95
+ raise
78
96
  end
79
97
 
80
98
  def decode_jwt_payload(token, cert_key)
81
99
  JWT.decode(token, cert_key, true, JWT_DEFAULTS).first
82
100
  rescue StandardError
83
- nil
101
+ return nil unless @raise_error
102
+
103
+ raise
84
104
  end
85
105
 
86
106
  def authorize(payload)
@@ -12,10 +12,10 @@ module FirebaseIdToken
12
12
  # + {Certificates.private_key}
13
13
  # + {Certificates.certificate}
14
14
  class Certificates
15
- # `.find` is stabbed to always return the same certificate.
15
+ # `.find` is stubbed to always return the same certificate.
16
16
  # @param [String] kid Key ID
17
17
  # @return [nil, OpenSSL::X509::Certificate]
18
- def self.find(kid)
18
+ def self.find(kid, raise_error: false)
19
19
  cert = certificate
20
20
  OpenSSL::X509::Certificate.new cert
21
21
  end
@@ -1,3 +1,3 @@
1
1
  module FirebaseIdToken
2
- VERSION = '2.3.2'
2
+ VERSION = '2.4.0'
3
3
  end
@@ -128,6 +128,28 @@ module FirebaseIdToken
128
128
  end
129
129
  end
130
130
 
131
+ describe '.find!' do
132
+ context 'without certificates in Redis database' do
133
+ it 'raises a exception' do
134
+ expect{ described_class.find!(kid)}.
135
+ to raise_error(Exceptions::NoCertificatesError)
136
+ end
137
+ end
138
+ context 'with certificates in Redis database' do
139
+ it 'returns a OpenSSL::X509::Certificate when it finds the kid' do
140
+ described_class.request
141
+ expect(described_class.find!(kid)).to be_a(OpenSSL::X509::Certificate)
142
+ end
143
+
144
+ it 'raises a CertificateNotFound error when it can not find the kid' do
145
+ described_class.request
146
+ expect { described_class.find!('') }
147
+ .to raise_error(Exceptions::CertificateNotFound, /Unable to find/)
148
+ end
149
+ end
150
+
151
+ end
152
+
131
153
  describe '.ttl' do
132
154
  it 'returns a positive number when has certificates in Redis' do
133
155
  described_class.request
@@ -3,11 +3,14 @@ require 'spec_helper'
3
3
  module FirebaseIdToken
4
4
  describe Signature do
5
5
  let(:jwt) { JSON.parse File.read('spec/fixtures/files/jwt.json') }
6
+ let(:raise_certificates_error) { false }
6
7
 
7
- let (:mock_certificates) {
8
- allow(Certificates).to receive(:find).with(an_instance_of(String)) {
9
- OpenSSL::X509::Certificate.new(jwt['certificate']) }
10
- }
8
+ let(:mock_certificates) do
9
+ allow(Certificates)
10
+ .to(receive(:find))
11
+ .with(an_instance_of(String), raise_error: raise_certificates_error)
12
+ .and_return(OpenSSL::X509::Certificate.new(jwt['certificate']))
13
+ end
11
14
 
12
15
  before :each do
13
16
  mock_certificates
@@ -29,5 +32,22 @@ module FirebaseIdToken
29
32
  expect(described_class.verify('aaa')).to be(nil)
30
33
  end
31
34
  end
35
+
36
+ describe '#verify!' do
37
+ let(:raise_certificates_error) { true }
38
+ it 'returns a Hash when the signature is valid' do
39
+ expect(described_class.verify!(jwt['jwt_token'])).to be_a(Hash)
40
+ end
41
+
42
+ it 'raises an error when the signature is invalid' do
43
+ expect { described_class.verify!(jwt['bad_jwt_token']) }
44
+ .to raise_error(JWT::VerificationError)
45
+ end
46
+
47
+ it 'raises an error with a invalid key format' do
48
+ expect { described_class.verify!('aaa') }
49
+ .to raise_error(JWT::DecodeError, /too many/)
50
+ end
51
+ end
32
52
  end
33
53
  end
metadata CHANGED
@@ -1,43 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: firebase_id_token
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fernando Schuindt
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-15 00:00:00.000000000 Z
11
+ date: 2020-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
17
20
  - - ">="
18
21
  - !ruby/object:Gem::Version
19
- version: '0'
22
+ version: 1.17.2
20
23
  type: :development
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.17'
24
30
  - - ">="
25
31
  - !ruby/object:Gem::Version
26
- version: '0'
32
+ version: 1.17.2
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: rake
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '10.0'
39
+ version: '12.3'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 12.3.3
34
43
  type: :development
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
47
  - - "~>"
39
48
  - !ruby/object:Gem::Version
40
- version: '10.0'
49
+ version: '12.3'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 12.3.3
41
53
  - !ruby/object:Gem::Dependency
42
54
  name: rspec
43
55
  requirement: !ruby/object:Gem::Requirement
@@ -214,6 +226,7 @@ files:
214
226
  - ".rspec"
215
227
  - ".travis.yml"
216
228
  - ".yardopts"
229
+ - CHANGELOG.md
217
230
  - CODE_OF_CONDUCT.md
218
231
  - Gemfile
219
232
  - LICENSE.txt
@@ -221,10 +234,12 @@ files:
221
234
  - Rakefile
222
235
  - bin/console
223
236
  - bin/setup
237
+ - docker-compose.yml
224
238
  - firebase_id_token.gemspec
225
239
  - lib/firebase_id_token.rb
226
240
  - lib/firebase_id_token/certificates.rb
227
241
  - lib/firebase_id_token/configuration.rb
242
+ - lib/firebase_id_token/exceptions/certificate_not_found.rb
228
243
  - lib/firebase_id_token/exceptions/certificates_request_error.rb
229
244
  - lib/firebase_id_token/exceptions/certificates_ttl_error.rb
230
245
  - lib/firebase_id_token/exceptions/no_certificates_error.rb