firebase_id_token 2.3.1 → 2.5.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 +4 -4
- data/.travis.yml +2 -2
- data/CHANGELOG.md +121 -0
- data/README.md +1 -1
- data/docker-compose.yml +9 -0
- data/firebase_id_token.gemspec +3 -5
- data/lib/firebase_id_token/certificates.rb +25 -4
- data/lib/firebase_id_token/exceptions/certificate_not_found.rb +8 -0
- data/lib/firebase_id_token/signature.rb +45 -12
- data/lib/firebase_id_token/testing/certificates.rb +6 -2
- data/lib/firebase_id_token/version.rb +1 -1
- data/lib/firebase_id_token.rb +2 -1
- data/spec/firebase_id_token/certificates_spec.rb +164 -0
- data/spec/firebase_id_token/configuration_spec.rb +33 -0
- data/spec/firebase_id_token/signature_spec.rb +53 -0
- data/spec/firebase_id_token/signature_test_spec.rb +28 -0
- data/spec/firebase_id_token_spec.rb +46 -0
- data/spec/fixtures/files/.about_payload_file +3 -0
- data/spec/fixtures/files/certificates.json +5 -0
- data/spec/fixtures/files/jwt.json +6 -0
- data/spec/fixtures/files/payload.json +24 -0
- data/spec/spec_helper.rb +19 -0
- metadata +59 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d323f3f19f0e2cfa9f511adac526f38261ee28386d4abc210a22e26358008143
|
4
|
+
data.tar.gz: 82095062bbd88ebfe9ddbee3f769f2bc9e4fb0b9289fa673f4bf81d6a24132d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d056894ee1051fb9ccb0984624282805f153aca7e9bb41b5d3b39a93b749150311e45e11f7e182fdb4ee1814bea722a5fc49ddb975394f319edb3bbea7424d6
|
7
|
+
data.tar.gz: 998d1b74cdf9b036892e12ab9e7c271417ead8d18c6bbb8dcea04ea555c4fe6a856b79840872676c4aa530726132826f795c686ba5096502004a22ab7df82751
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,121 @@
|
|
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
|
+
## [2.5.0] - 2022-04-13
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
- Local Code Execution through Argument Injection via dash leading git url parameter in Gemfile [CVE-2021-43809](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-43809).
|
13
|
+
- Dependency Confusion in Bundler [CVE-2020-36327](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-36327).
|
14
|
+
- Insecure path handling in Bundler [CVE-2019-3881](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-3881).
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
- Using Bundler 2.3.11.
|
18
|
+
- Using `Time.current` instead of `Time.now` to work with timezones [PR 34](https://github.com/fschuindt/firebase_id_token/pull/34).
|
19
|
+
- Caching certificates on memory using `Thread` to avoid unnecessary calls into Redis [PR 33](https://github.com/fschuindt/firebase_id_token/pull/33).
|
20
|
+
|
21
|
+
## [2.4.0] - 2020-05-02
|
22
|
+
|
23
|
+
### Fixed
|
24
|
+
- Rake development dependency vulnerability [CVE-2020-8130](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-8130).
|
25
|
+
|
26
|
+
### Changed
|
27
|
+
- Using Bundler 1.17.2.
|
28
|
+
|
29
|
+
### Added
|
30
|
+
- Ability to raise errors when verifying tokens.
|
31
|
+
- `FirebaseIdToken::Certificates.find!` method.
|
32
|
+
- `FirebaseIdToken::Signatures.verify!` method.
|
33
|
+
- `FirebaseIdToken::Exceptions::CertificateNotFound` exception.
|
34
|
+
- `:raise_error` option to `FirebaseIdToken::Signature.verify`.
|
35
|
+
- `CHANGELOG.md` file.
|
36
|
+
|
37
|
+
## [2.3.2] - 2020-02-15
|
38
|
+
|
39
|
+
### Fixed
|
40
|
+
- Certificate fixture not accessible when packing Gem into Rails application.
|
41
|
+
|
42
|
+
### Changed
|
43
|
+
- Bumped Bundler version to 1.14.
|
44
|
+
|
45
|
+
## [2.3.1] - 2019-08-13
|
46
|
+
|
47
|
+
### Fixed
|
48
|
+
- Certificate fixture reading issue.
|
49
|
+
|
50
|
+
### Added
|
51
|
+
- Test mode.
|
52
|
+
- Test mode documentation.
|
53
|
+
|
54
|
+
## [2.3.0] - 2018-06-18
|
55
|
+
|
56
|
+
### Changed
|
57
|
+
- Started to use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
58
|
+
- Runtime dependencies versions upgraded.
|
59
|
+
- Use Redis `>= 3.3.3`.
|
60
|
+
|
61
|
+
## [2.2.0] - 2018-05-21
|
62
|
+
*Nothing tracked, release skipped.*
|
63
|
+
|
64
|
+
## [2.1.0] - 2018-04-09
|
65
|
+
|
66
|
+
### Fixed
|
67
|
+
- `FirebaseIdToken::Signature.verify` now returns `nil` for newly issued tokens.
|
68
|
+
|
69
|
+
## [2.0.0] - 2017-12-09
|
70
|
+
|
71
|
+
### Fixed
|
72
|
+
- Typo on Rake task `force_request` name.
|
73
|
+
|
74
|
+
## [1.3.0] - 2017-09-15
|
75
|
+
|
76
|
+
### Changed
|
77
|
+
- Renamed `Certificates.request_anyway` to `Certificates.request!` (`Certificates.request_anyway` was kept for backwards compatibility.
|
78
|
+
|
79
|
+
### Fixed
|
80
|
+
- Documentaiton typos.
|
81
|
+
- Initializer typos.
|
82
|
+
|
83
|
+
## [1.2.2] - 2017-04-29
|
84
|
+
|
85
|
+
### Changed
|
86
|
+
- Recommended people to use cron tasks instead of background jobs.
|
87
|
+
- Set certificates TTL based on cache-control's max-age.
|
88
|
+
- Documentation now warns about request during application start in Rails.
|
89
|
+
|
90
|
+
### Fixed
|
91
|
+
- Documentation typos.
|
92
|
+
|
93
|
+
## [1.2.1] - 2017-04-27
|
94
|
+
|
95
|
+
### Changed
|
96
|
+
- Small improvements on documentation.
|
97
|
+
|
98
|
+
## [1.2.0] - 2017-04-26
|
99
|
+
|
100
|
+
### Changed
|
101
|
+
- The Gem was marked as "ready to use".
|
102
|
+
|
103
|
+
## [1.1.0] - 2017-04-26
|
104
|
+
*Nothing tracked.*
|
105
|
+
|
106
|
+
## [1.0.0] - 2017-04-26
|
107
|
+
*Version removed.*
|
108
|
+
|
109
|
+
## [0.1.0] - 2017-04-23
|
110
|
+
*Version removed.*
|
111
|
+
|
112
|
+
[2.5.0]: https://github.com/fschuindt/firebase_id_token/compare/2.4.0...2.5.0
|
113
|
+
[2.4.0]: https://github.com/fschuindt/firebase_id_token/compare/2.3.2...2.4.0
|
114
|
+
[2.3.2]: https://github.com/fschuindt/firebase_id_token/compare/2.3.1...2.3.2
|
115
|
+
[2.3.1]: https://github.com/fschuindt/firebase_id_token/compare/2.3.0...2.3.1
|
116
|
+
[2.3.0]: https://github.com/fschuindt/firebase_id_token/compare/2.0.0...2.3.0
|
117
|
+
[2.1.0]: https://github.com/fschuindt/firebase_id_token/compare/2.0.0...2.1.0
|
118
|
+
[2.0.0]: https://github.com/fschuindt/firebase_id_token/compare/1.3.0...2.0.0
|
119
|
+
[1.3.0]: https://github.com/fschuindt/firebase_id_token/compare/1.2.2...1.3.0
|
120
|
+
[1.2.2]: https://github.com/fschuindt/firebase_id_token/compare/1.2.1...1.2.2
|
121
|
+
[1.2.1]: https://github.com/fschuindt/firebase_id_token/compare/1.2.0...1.2.1
|
data/README.md
CHANGED
data/docker-compose.yml
ADDED
data/firebase_id_token.gemspec
CHANGED
@@ -17,15 +17,13 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.homepage = 'https://github.com/fschuindt/firebase_id_token'
|
18
18
|
spec.license = 'MIT'
|
19
19
|
|
20
|
-
spec.files = `git ls-files -z`.split("\x0")
|
21
|
-
f.match(%r{^(test|spec|features)/})
|
22
|
-
end
|
20
|
+
spec.files = `git ls-files -z`.split("\x0")
|
23
21
|
spec.bindir = 'exe'
|
24
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
23
|
spec.require_paths = ['lib']
|
26
24
|
|
27
|
-
spec.add_development_dependency 'bundler', '~>
|
28
|
-
spec.add_development_dependency 'rake', '~>
|
25
|
+
spec.add_development_dependency 'bundler', '~> 2.3', '>= 2.3.11'
|
26
|
+
spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.3'
|
29
27
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
30
28
|
spec.add_development_dependency 'redcarpet', '~> 3.4', '>= 3.4.0'
|
31
29
|
spec.add_development_dependency 'simplecov', '~> 0.14.1'
|
@@ -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
|
-
|
120
|
-
|
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
|
@@ -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,34 @@ 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
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
81
|
+
var_name = :_firebase_id_token_cert
|
82
|
+
Thread.current[var_name] ||= {
|
83
|
+
cert: nil,
|
84
|
+
expires_at: Time.now.utc - 1
|
85
|
+
}
|
86
|
+
|
87
|
+
if Thread.current[var_name][:expires_at] <= Time.now.utc
|
88
|
+
Thread.current[var_name] = {
|
89
|
+
cert: firebase_id_token_certificates.find(@kid, raise_error: @raise_error),
|
90
|
+
expires_at: Time.now.utc + firebase_id_token_certificates.ttl
|
91
|
+
}
|
69
92
|
end
|
93
|
+
|
94
|
+
certificate = Thread.current[var_name][:cert]
|
95
|
+
return unless certificate
|
96
|
+
|
97
|
+
payload = decode_jwt_payload(@jwt_token, certificate.public_key)
|
98
|
+
authorize payload
|
70
99
|
end
|
71
100
|
|
72
101
|
private
|
@@ -74,13 +103,17 @@ module FirebaseIdToken
|
|
74
103
|
def extract_kid(jwt_token)
|
75
104
|
JWT.decode(jwt_token, nil, false).last['kid']
|
76
105
|
rescue StandardError
|
77
|
-
'none'
|
106
|
+
return 'none' unless @raise_error
|
107
|
+
|
108
|
+
raise
|
78
109
|
end
|
79
110
|
|
80
111
|
def decode_jwt_payload(token, cert_key)
|
81
112
|
JWT.decode(token, cert_key, true, JWT_DEFAULTS).first
|
82
113
|
rescue StandardError
|
83
|
-
nil
|
114
|
+
return nil unless @raise_error
|
115
|
+
|
116
|
+
raise
|
84
117
|
end
|
85
118
|
|
86
119
|
def authorize(payload)
|
@@ -97,8 +130,8 @@ module FirebaseIdToken
|
|
97
130
|
end
|
98
131
|
|
99
132
|
def still_valid?(payload)
|
100
|
-
payload['exp'].to_i > Time.
|
101
|
-
payload['iat'].to_i <= Time.
|
133
|
+
payload['exp'].to_i > Time.current.to_i &&
|
134
|
+
payload['iat'].to_i <= Time.current.to_i
|
102
135
|
end
|
103
136
|
|
104
137
|
def issuer_authorized?(payload)
|
@@ -12,10 +12,10 @@ module FirebaseIdToken
|
|
12
12
|
# + {Certificates.private_key}
|
13
13
|
# + {Certificates.certificate}
|
14
14
|
class Certificates
|
15
|
-
# `.find` is
|
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
|
@@ -80,6 +80,10 @@ module FirebaseIdToken
|
|
80
80
|
)
|
81
81
|
)
|
82
82
|
end
|
83
|
+
|
84
|
+
def self.ttl
|
85
|
+
10
|
86
|
+
end
|
83
87
|
end
|
84
88
|
end
|
85
89
|
end
|
data/lib/firebase_id_token.rb
CHANGED
@@ -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
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FirebaseIdToken
|
4
|
+
describe Certificates do
|
5
|
+
let (:redis) { Redis::Namespace.new 'firebase_id_token', redis: Redis.new }
|
6
|
+
let (:certs) { File.read('spec/fixtures/files/certificates.json') }
|
7
|
+
let (:cache) { 'public, max-age=19302, must-revalidate, no-transform' }
|
8
|
+
let (:low_cache) { 'public, max-age=2160, must-revalidate, no-transform' }
|
9
|
+
let (:kid) { JSON.parse(certs).first[0] }
|
10
|
+
let (:expires_in) { (DateTime.now + (5/24r)).to_s }
|
11
|
+
let (:response) { double }
|
12
|
+
|
13
|
+
let (:mock_response) {
|
14
|
+
allow(response).to receive(:code) { 200 }
|
15
|
+
allow(response).to receive(:headers) { { 'cache-control' => cache } }
|
16
|
+
allow(response).to receive(:body) { certs }
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:mock_request) {
|
20
|
+
mock_response
|
21
|
+
allow(HTTParty).to receive(:get).
|
22
|
+
with(an_instance_of(String)) { response }
|
23
|
+
}
|
24
|
+
|
25
|
+
before :each do
|
26
|
+
redis.del 'certificates'
|
27
|
+
mock_request
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#request' do
|
31
|
+
it 'requests certificates when Redis database is empty' do
|
32
|
+
expect(HTTParty).to receive(:get).
|
33
|
+
with(FirebaseIdToken::Certificates::URL)
|
34
|
+
described_class.request
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'does not requests certificates when Redis database is written' do
|
38
|
+
expect(HTTParty).to receive(:get).
|
39
|
+
with(FirebaseIdToken::Certificates::URL).once
|
40
|
+
2.times { described_class.request }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#request!' do
|
45
|
+
it 'always requests certificates' do
|
46
|
+
expect(HTTParty).to receive(:get).
|
47
|
+
with(FirebaseIdToken::Certificates::URL).twice
|
48
|
+
2.times { described_class.request! }
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'sets the certificate expiration time as Redis TTL' do
|
52
|
+
described_class.request!
|
53
|
+
expect(redis.ttl('certificates')).to be > 3600
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'raises a error when certificates expires in less than 1 hour' do
|
57
|
+
allow(response).to receive(:headers) {{'cache-control' => low_cache}}
|
58
|
+
expect{ described_class.request! }.
|
59
|
+
to raise_error(Exceptions::CertificatesTtlError)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'raises a error when HTTP response code is other than 200' do
|
63
|
+
allow(response).to receive(:code) { 401 }
|
64
|
+
expect{ described_class.request! }.
|
65
|
+
to raise_error(Exceptions::CertificatesRequestError)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#request_anyway' do
|
70
|
+
it 'also requests certificates' do
|
71
|
+
expect(HTTParty).to receive(:get).
|
72
|
+
with(FirebaseIdToken::Certificates::URL)
|
73
|
+
|
74
|
+
described_class.request_anyway
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '.present?' do
|
79
|
+
it 'returns false when Redis database is empty' do
|
80
|
+
expect(described_class.present?).to be(false)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'returns true when Redis database is written' do
|
84
|
+
described_class.request
|
85
|
+
expect(described_class.present?).to be(true)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '.all' do
|
90
|
+
context 'before requesting certificates' do
|
91
|
+
it 'returns a empty Array' do
|
92
|
+
expect(described_class.all).to eq([])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'after requesting certificates' do
|
97
|
+
it 'returns a array of hashes: String keys' do
|
98
|
+
described_class.request
|
99
|
+
expect(described_class.all.first.keys[0]).to be_a(String)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns a array of hashes: OpenSSL::X509::Certificate values' do
|
103
|
+
described_class.request
|
104
|
+
expect(described_class.all.first.values[0]).
|
105
|
+
to be_a(OpenSSL::X509::Certificate)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '.find' do
|
111
|
+
context 'without certificates in Redis database' do
|
112
|
+
it 'raises a exception' do
|
113
|
+
expect{ described_class.find(kid)}.
|
114
|
+
to raise_error(Exceptions::NoCertificatesError)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'with certificates in Redis database' do
|
119
|
+
it 'returns a OpenSSL::X509::Certificate when it finds the kid' do
|
120
|
+
described_class.request
|
121
|
+
expect(described_class.find(kid)).to be_a(OpenSSL::X509::Certificate)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'returns nil when it can not find the kid' do
|
125
|
+
described_class.request
|
126
|
+
expect(described_class.find('')).to be(nil)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
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
|
+
|
153
|
+
describe '.ttl' do
|
154
|
+
it 'returns a positive number when has certificates in Redis' do
|
155
|
+
described_class.request
|
156
|
+
expect(described_class.ttl).to be > 0
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'returns zero when has no certificates in Redis' do
|
160
|
+
expect(described_class.ttl).to eq(0)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FirebaseIdToken
|
4
|
+
describe Configuration do
|
5
|
+
describe '.project_ids' do
|
6
|
+
it 'sets [] as default' do
|
7
|
+
expect(Configuration.new.project_ids).to eq([])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.project_ids=' do
|
12
|
+
it 'changes default values' do
|
13
|
+
config = Configuration.new
|
14
|
+
config.project_ids = String.new
|
15
|
+
expect(config.project_ids).to be_a(String)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.redis' do
|
20
|
+
it 'sets a Redis instance as default' do
|
21
|
+
expect(Configuration.new.redis).to be_a(Redis)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '.redis=' do
|
26
|
+
it 'changes default values' do
|
27
|
+
config = Configuration.new
|
28
|
+
config.redis = String.new
|
29
|
+
expect(config.redis).to be_a(String)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FirebaseIdToken
|
4
|
+
describe Signature do
|
5
|
+
let(:jwt) { JSON.parse File.read('spec/fixtures/files/jwt.json') }
|
6
|
+
let(:raise_certificates_error) { false }
|
7
|
+
|
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
|
14
|
+
|
15
|
+
before :each do
|
16
|
+
mock_certificates
|
17
|
+
FirebaseIdToken.configure do |config|
|
18
|
+
config.project_ids = ['firebase-id-token']
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#verify' do
|
23
|
+
it 'returns a Hash when the signature is valid' do
|
24
|
+
expect(described_class.verify(jwt['jwt_token'])).to be_a(Hash)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns nil when the signature is invalid' do
|
28
|
+
expect(described_class.verify(jwt['bad_jwt_token'])).to be(nil)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'returns nil with a invalid key format' do
|
32
|
+
expect(described_class.verify('aaa')).to be(nil)
|
33
|
+
end
|
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
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FirebaseIdToken
|
4
|
+
describe Signature do
|
5
|
+
let(:jwt) { JSON.parse File.read('spec/fixtures/files/jwt.json') }
|
6
|
+
let(:payload) { JSON.parse File.read('spec/fixtures/files/payload.json') }
|
7
|
+
let(:rsa_private) { OpenSSL::PKey::RSA.new(FirebaseIdToken::Testing::Certificates.private_key) }
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
FirebaseIdToken.configure do |config|
|
11
|
+
config.project_ids = ['firebase-id-token']
|
12
|
+
end
|
13
|
+
FirebaseIdToken.test!
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#verify' do
|
17
|
+
|
18
|
+
it 'test mode is valid' do
|
19
|
+
expect(described_class.verify(jwt['jwt_token'])).to be_a(Hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'test mode encode is valid' do
|
23
|
+
JWT.encode payload, rsa_private, 'RS256'
|
24
|
+
expect(described_class.verify(jwt['jwt_token'])).to be_a(Hash)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe FirebaseIdToken do
|
4
|
+
let(:jwt) { JSON.parse File.read('spec/fixtures/files/jwt.json') }
|
5
|
+
|
6
|
+
let (:mock_certificates) {
|
7
|
+
allow(FirebaseIdToken::Certificates).to receive(:find).
|
8
|
+
with(an_instance_of(String)) {
|
9
|
+
OpenSSL::X509::Certificate.new(jwt['certificate']) }
|
10
|
+
}
|
11
|
+
|
12
|
+
it 'has a version number' do
|
13
|
+
expect(FirebaseIdToken::VERSION).not_to be nil
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#configure' do
|
17
|
+
before :each do
|
18
|
+
mock_certificates
|
19
|
+
FirebaseIdToken.configure do |config|
|
20
|
+
config.project_ids = ['firebase-id-token']
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sets global project_ids' do
|
25
|
+
expect(FirebaseIdToken::Signature.verify(jwt['jwt_token'])).to be_a(Hash)
|
26
|
+
end
|
27
|
+
|
28
|
+
after :each do
|
29
|
+
FirebaseIdToken.reset
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#reset' do
|
34
|
+
before :each do
|
35
|
+
FirebaseIdToken.configure do |config|
|
36
|
+
config.project_ids = 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'resets the configuration' do
|
41
|
+
FirebaseIdToken.reset
|
42
|
+
config = FirebaseIdToken.configuration
|
43
|
+
expect(config.project_ids).to eq([])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
{
|
2
|
+
"1d6d911c0c01c7871befbedab6fe4aa932cb14b1":"-----BEGIN CERTIFICATE-----\nMIIDHDCCAgSgAwIBAgIIcM5ipUjH60gwDQYJKoZIhvcNAQEFBQAwMTEvMC0GA1UE\nAxMmc2VjdXJldG9rZW4uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wHhcNMTcw\nNDIwMDA0NTI2WhcNMTcwNDIzMDExNTI2WjAxMS8wLQYDVQQDEyZzZWN1cmV0b2tl\nbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAL1PdoFtJ6YI+TLRPZcNNElRlOHmGGvBvilmgZEa3Pn5P6BH\n7NIi1PuLlRKoAOh+m+NBxEP+o6X6SVyLxhmLqoUmNxJP1UzdP4iUV4taSe5Ar6LG\nuPFwzzFTygHVZmiED+0/YhaigcPWakU29rDKBBzi3mbHOrftCENc4MjSj+VgN0f7\namTXEHvs/mnCaKs9llIKLFNkxZMCLYYUI8z/fAswkvF+16jr1hWMQhJ0EtsrS7+s\nAaDainDxRHQdL/C3invOp/+MdtV9JD76uTcwRaJnevtMAwReGsuVuQ9ytueFMjDR\ndwAcXEj7DFum7UlG4YUJNyrwfFMP7STdXMDIcU0CAwEAAaM4MDYwDAYDVR0TAQH/\nBAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJ\nKoZIhvcNAQEFBQADggEBACUU6SbF+W/PIQLu4JKc2AuyqFG3+HMHTggq6lFDoe4h\nrdOFf1GwGBir5QLRp4VteYMpHuluZ30l+83XfPW82Bi3Xg+oXCs/ZdlwOSYB60R1\nJHLh2fnjquydwTDnHvfiGKPbE+/BgIbW7CfKRjdZxOTx/kbyymhriT2vBSf9nePF\nH9qEtcs/Y95PEdt28Jrjcn4r9tqnNb9w3J6bN0VGndegvwtrPzacyXXsawOny0Ij\n/1I7CJ19bYFQ9dPjvQzUUssUbSmCfl0p+s+6FzzWbaZxcOga2NoqESU522s1VVyx\niKFq8KyT6RD1RKr3vQwULR7h5HU0pkPJz3UCLpy6udw=\n-----END CERTIFICATE-----\n",
|
3
|
+
"1dd4bb29a77e0d8f3ddcb6af82444bee2e1f8f41":"-----BEGIN CERTIFICATE-----\nMIIDHDCCAgSgAwIBAgIIff9h3dvZ7S0wDQYJKoZIhvcNAQEFBQAwMTEvMC0GA1UE\nAxMmc2VjdXJldG9rZW4uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wHhcNMTcw\nNDIxMDA0NTI2WhcNMTcwNDI0MDExNTI2WjAxMS8wLQYDVQQDEyZzZWN1cmV0b2tl\nbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAOkr+xUfSLz88cuxUEodF9YPLQDjIU/6EOIpkOmI8hLbEgPL\nXtWdudzWlZ231Owy6bhywc+WZLgDnAdAU0RCoy0kZkiAShU5qGWMLp59gC9VCS/Y\nPsw6N8VJM6G4Qekjdy/X/0QRSi26RdIbdlKuN+NF4gN0feRk8gXxfeCYzF2FxN8q\nyH8uIwpchHd0rix0sKjXxE3K/4Sw+NxNIcdVyYuu6qvCs0L+vRT7AYBWPOveTPSj\nnbf8hTAx/Le2hDJZ/aARe7lZNGGqgrJweXT9XB6SEG0mzh/9ShaA22Tlsrhb/1K/\n1xMDdCdS/6cCcHhEVw1tsZHN9GpyfQQAdYjXvncCAwEAAaM4MDYwDAYDVR0TAQH/\nBAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJ\nKoZIhvcNAQEFBQADggEBAHpCWcikPhudhZ4ZfO+Y52CD6N50w+dse0X5lNKK9D7g\nC/6At8KY74NAD4wiCv6l3f6Eyq0kIlOwjHykzmTgrwcY3GI9FauCPkzl1pzfw5Cr\n6kuePTjMd67vi3XanQ2ZhM0g/CUQHR8VYELwMhh8dPaI/enmq7Yw7UAUKxDmI4zD\nz8VTb/A2LA+HgIk+X9lRW5fSHCm2ujN8VzYUr/BKx6U58x/qVp1Y1J0mXJdrmyK6\ngPb4Ro0/zPscMbeKNqNbTeCT5YXTNtU9+Zzs3OJ+e283EyR3h0VfdqD266kr0yuy\njq/v/Rplwrf8fHGEkdVTApWUb1nSbK0obLzkqb3ut9Q=\n-----END CERTIFICATE-----\n",
|
4
|
+
"e2e353f4bd0fd6189e532c2377771439d903c346":"-----BEGIN CERTIFICATE-----\nMIIDHDCCAgSgAwIBAgIIFqTX4DUSi0gwDQYJKoZIhvcNAQEFBQAwMTEvMC0GA1UE\nAxMmc2VjdXJldG9rZW4uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wHhcNMTcw\nNDE5MDA0NTI2WhcNMTcwNDIyMDExNTI2WjAxMS8wLQYDVQQDEyZzZWN1cmV0b2tl\nbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAKxLXZ0dYY5SRXyG2FiiEUXUb2qEX5u6svjiexIEuvO/9eP2\n4B/dkICJLI7RfQcogtkn5SCi7Cd/szuLT5z1AeGQdqgU7OBVgMGyzG4bf03DNqfh\noRghroG+mIrvE/4Qx2x2reokc0ShlrBBpZUh/EU89NAvJkudp0MqtoGNhzH6CQ5X\nmUXThpu7RVb7ciHrW1HRlMZjCNcLDkUEm4FPGtBT1T2zvCOLjrOG9BmhX97PtV2l\nFrbzIG0Z0nYa3y+hIyNfVwC+CjqNRHYdmDDt3fEM7B9IlS9wpd6waphxY6j09VNy\nCQtKuRhenReiY2uM8sRfZvqNH+guOkb2NZ77hW8CAwEAAaM4MDYwDAYDVR0TAQH/\nBAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJ\nKoZIhvcNAQEFBQADggEBADUioofGGbdCcSZdgVruwmpMl3FYWu+c5OknBiLyQmtj\nH7okp0DXXq0k+JXe3Q5b8AoOQnDbS0drETGB9Bi145/cv3KfF9cHw+OLF1/sOLDD\n23FvvZWYjWngOIG7tNeMUprb981lc4xUrW8ViqtbPUqJNO5dEPU1MHPm7oxTavH9\nm7nPT7xzI5TuaQnQ0Dql8nlirJOCu2DO47ug4+J5C6fsHPW3c4Ui2VdLtNGDHm2L\nQCAOfti8SukoHF9z1NnHX4ODkEHtALoDN/XygMabgLBuuZneCJShEYsNNtN3Tl0G\nyKRpTYkiDzegpVgehCjQK3EYM2io0uxDgVb+9fT2WpA=\n-----END CERTIFICATE-----\n"
|
5
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
{
|
2
|
+
"private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQCrvJRW05yKQxx3+PdiysRKR/N+VqYv9+b/76C3zC/vk9ACkWTN\n/dcPMzIXVIdDMU+r1o8HF3mOXNhCFWGSfZ7r1dMe961BQtxu1DagC7Ff+XZZL0Mu\n0W0Y/GmP7yTrsie7wCq4QiHj2HBtUtze/uC6DT8Qcthg46LUJBqeh9FiIwIDAQAB\nAoGAEGK80I/+Np7yn2vMxstL8T5uOBayYo9HphHKBt9fj39N8IDI2nKmy1d6Jwm0\noi+ZR28AVI/j1DZ9l8iMd7qup+/D5CdTt89u8fTUlQkCjAQQsRBneq5MJRKI+5eA\nJDJmx7p7CUUqjnIcFfbBz0NLTDZso11Vp+BDfbDpKv37nskCQQDZimWuxa7rK6UZ\nXGDl8LxEiM27US67kDu8iS3VdQWEKIhhQoea/zNKPMkQsc2+CPggQTcG/2WuPEYJ\nO1bPz7HPAkEAyhknhziWREEBQRLp4qsakozMIn4iuuaC00zpLwcnyOqFPaHS5CTL\nI7GxpwN6Ld1N/nqvYGyk/dRb5Ul7v27DbQJAUMsJwMNCl6z6AFVC16N1CK8WWX9p\nL9f9l6QLFcAEcHTtUdH3syUc03GH619d3jpOjQwrd7na9b8E8+DJ+RxWGQJAI8cE\nOmoIIBkp8a05fokv8RW/5bNSzqeULXgGJ+8qWeU6pUiKnxzsYWtJuflhndD5x71M\nYtOY+d6oThUONTuUmQJBAMGl/eaFU0AfA+xS/3Kt5JFKBbBVAByhL+Hd/27/rYZ5\n8YXDUQAgcykCS21JMrn41p4gwJnpG35PoV8qBIW9a94=\n-----END RSA PRIVATE KEY-----",
|
3
|
+
"certificate": "-----BEGIN CERTIFICATE-----\nMIIChDCCAe2gAwIBAgIBADANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJCRTEN\nMAsGA1UECgwEVGVzdDENMAsGA1UECwwEVGVzdDENMAsGA1UEAwwEVGVzdDAgFw0x\nNzA0MjQwMjE5MzRaGA8zMDE2MDgyNTAyMTkzNFowOjELMAkGA1UEBhMCQkUxDTAL\nBgNVBAoMBFRlc3QxDTALBgNVBAsMBFRlc3QxDTALBgNVBAMMBFRlc3QwgZ8wDQYJ\nKoZIhvcNAQEBBQADgY0AMIGJAoGBAKu8lFbTnIpDHHf492LKxEpH835Wpi/35v/v\noLfML++T0AKRZM391w8zMhdUh0MxT6vWjwcXeY5c2EIVYZJ9nuvV0x73rUFC3G7U\nNqALsV/5dlkvQy7RbRj8aY/vJOuyJ7vAKrhCIePYcG1S3N7+4LoNPxBy2GDjotQk\nGp6H0WIjAgMBAAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUFKl2\nnZaaeNZM/7dno9IbaEIvaXQwYgYDVR0jBFswWYAUFKl2nZaaeNZM/7dno9IbaEIv\naXShPqQ8MDoxCzAJBgNVBAYTAkJFMQ0wCwYDVQQKDARUZXN0MQ0wCwYDVQQLDARU\nZXN0MQ0wCwYDVQQDDARUZXN0ggEAMA0GCSqGSIb3DQEBBQUAA4GBAKkBvhUIRENB\nap0r9F7sKkRr8tJCCjBPIA+8e8XIKS3A3w6EI5ErRpv795rO80TBR4WZR9GhH8M1\nPXJ7FuaayCcPAl0febjl4z6ZciCSDpBdhbMpmq1d/kYU1H1qUokE2BxhNdcs/Q4w\n+5NnFGSkYm09tPzLWFPLoES9ynBF0N7l\n-----END CERTIFICATE-----",
|
4
|
+
"jwt_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEyM3F3ZSJ9.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZmlyZWJhc2UtaWQtdG9rZW4iLCJuYW1lIjoiVWdseSBCb2IiLCJwaWN0dXJlIjoiaHR0cHM6Ly9zb21ldXJsLmNvbS9waG90by5qcGciLCJhdWQiOiJmaXJlYmFzZS1pZC10b2tlbiIsImF1dGhfdGltZSI6MTQ5Mjk4MTE5MiwidXNlcl9pZCI6InRoZVVzZXJJRCIsInN1YiI6InRoZVVzZXJJRCIsImlhdCI6MTQ5Mjk4MTIwMCwiZXhwIjozMzAyOTAwMDAxNywiZW1haWwiOiJ1Z2x5Ym9iQGVtYWlsdXJsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7Imdvb2dsZS5jb20iOlsiMTAxMDEwMTAxMDEwMTAxMDEwMSJdLCJlbWFpbCI6WyJ1Z2x5Ym9iQGVtYWlsdXJsLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6Imdvb2dsZS5jb20ifX0.PjTLVli92r41PfptLsmfeKG-ThEj7SNM02yx8YSVf_b-DiYBqgDJrrFgUP29oy86K8v6bRzirgyq3fmxzBj9YIlhnOar_8QlEwr8U-m-85wcP3kDQmXE2QQRF8MQPMOVyPjn2skKNS3Wu1zZYoMT0dqygh2qxqvbouCGjum0REg",
|
5
|
+
"bad_jwt_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEyM3F3ZSJ9.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZmlyZWJhc2UtaWQtdG9rZW4iLCJuYW1lIjoiVWdseSBCb2IiLCJwaWN0dXJlIjoiaHR0cHM6Ly9zb21ldXJsLmNvbS9waG90by5qcGciLCJhdWQiOiJmaXJlYmFzZS1pZC10b2tlbiIsImF1dGhfdGltZSI6MTQ5Mjk4MTE5MiwidXNlcl9pZCI6InRoZVVzZXJJRCIsInN1YiI6InRoZVVzZXJJRCIsImlhdCI6MTQ5Mjk4MTIwMCwiZXhwIjozMzAyOTAwMDAxNywiZW1haWwiOiJ1Z2x5Ym9iQGVtYWlsdXJsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7Imdvb2dsZS5jb20iOlsiMTAxMDEwMTAxMDEwMTAxMDEwMSJdLCJlbWFpbCI6WyJ1Z2x5Ym9iQGVtYWlsdXJsLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6Imdvb2dsZS5jb20ifX0.rR9237-LJAgdt6ICqR7qoB5625tsat8uGTszB55rSEBEop8WFvXQo0maEfwtl_3JTxUfefDkLWUaBnFqArEMPoT9TIRuBOdJtVRDSxfNjio87DumsXPb97ALX2bTUU49fwDHGBiZqkBq9m0V49O-50MfyQqS0otC2p4_pRisS4o"
|
6
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"iss":"https://securetoken.google.com/firebase-id-token",
|
3
|
+
"name":"Ugly Bob",
|
4
|
+
"picture":"https://someurl.com/photo.jpg",
|
5
|
+
"aud":"firebase-id-token",
|
6
|
+
"auth_time":1492981192,
|
7
|
+
"user_id":"theUserID",
|
8
|
+
"sub":"theUserID",
|
9
|
+
"iat":1492981200,
|
10
|
+
"exp":33029000017,
|
11
|
+
"email":"uglybob@emailurl.com",
|
12
|
+
"email_verified":true,
|
13
|
+
"firebase":{
|
14
|
+
"identities":{
|
15
|
+
"google.com":[
|
16
|
+
"1010101010101010101"
|
17
|
+
],
|
18
|
+
"email":[
|
19
|
+
"uglybob@emailurl.com"
|
20
|
+
]
|
21
|
+
},
|
22
|
+
"sign_in_provider":"google.com"
|
23
|
+
}
|
24
|
+
}
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'redis'
|
6
|
+
require 'redis-namespace'
|
7
|
+
require 'httparty'
|
8
|
+
require 'jwt'
|
9
|
+
require 'firebase_id_token'
|
10
|
+
require 'pry'
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
# Enable flags like --only-failures and --next-failure
|
14
|
+
config.example_status_persistence_file_path = '.rspec_status'
|
15
|
+
|
16
|
+
config.expect_with :rspec do |c|
|
17
|
+
c.syntax = :expect
|
18
|
+
end
|
19
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: firebase_id_token
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fernando Schuindt
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,28 +16,40 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.3'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.3.11
|
20
23
|
type: :development
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
29
|
+
version: '2.3'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.3.11
|
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: '
|
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: '
|
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
|
@@ -56,22 +68,22 @@ dependencies:
|
|
56
68
|
name: redcarpet
|
57
69
|
requirement: !ruby/object:Gem::Requirement
|
58
70
|
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 3.4.0
|
62
71
|
- - "~>"
|
63
72
|
- !ruby/object:Gem::Version
|
64
73
|
version: '3.4'
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 3.4.0
|
65
77
|
type: :development
|
66
78
|
prerelease: false
|
67
79
|
version_requirements: !ruby/object:Gem::Requirement
|
68
80
|
requirements:
|
69
|
-
- - ">="
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
version: 3.4.0
|
72
81
|
- - "~>"
|
73
82
|
- !ruby/object:Gem::Version
|
74
83
|
version: '3.4'
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 3.4.0
|
75
87
|
- !ruby/object:Gem::Dependency
|
76
88
|
name: simplecov
|
77
89
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,22 +102,22 @@ dependencies:
|
|
90
102
|
name: codeclimate-test-reporter
|
91
103
|
requirement: !ruby/object:Gem::Requirement
|
92
104
|
requirements:
|
93
|
-
- - ">="
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
version: 1.0.0
|
96
105
|
- - "~>"
|
97
106
|
- !ruby/object:Gem::Version
|
98
107
|
version: '1.0'
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.0.0
|
99
111
|
type: :development
|
100
112
|
prerelease: false
|
101
113
|
version_requirements: !ruby/object:Gem::Requirement
|
102
114
|
requirements:
|
103
|
-
- - ">="
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
version: 1.0.0
|
106
115
|
- - "~>"
|
107
116
|
- !ruby/object:Gem::Version
|
108
117
|
version: '1.0'
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 1.0.0
|
109
121
|
- !ruby/object:Gem::Dependency
|
110
122
|
name: pry
|
111
123
|
requirement: !ruby/object:Gem::Requirement
|
@@ -144,22 +156,22 @@ dependencies:
|
|
144
156
|
name: redis-namespace
|
145
157
|
requirement: !ruby/object:Gem::Requirement
|
146
158
|
requirements:
|
147
|
-
- - ">="
|
148
|
-
- !ruby/object:Gem::Version
|
149
|
-
version: 1.6.0
|
150
159
|
- - "~>"
|
151
160
|
- !ruby/object:Gem::Version
|
152
161
|
version: '1.6'
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: 1.6.0
|
153
165
|
type: :runtime
|
154
166
|
prerelease: false
|
155
167
|
version_requirements: !ruby/object:Gem::Requirement
|
156
168
|
requirements:
|
157
|
-
- - ">="
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
version: 1.6.0
|
160
169
|
- - "~>"
|
161
170
|
- !ruby/object:Gem::Version
|
162
171
|
version: '1.6'
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: 1.6.0
|
163
175
|
- !ruby/object:Gem::Dependency
|
164
176
|
name: httparty
|
165
177
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,22 +196,22 @@ dependencies:
|
|
184
196
|
name: jwt
|
185
197
|
requirement: !ruby/object:Gem::Requirement
|
186
198
|
requirements:
|
187
|
-
- - ">="
|
188
|
-
- !ruby/object:Gem::Version
|
189
|
-
version: 2.1.0
|
190
199
|
- - "~>"
|
191
200
|
- !ruby/object:Gem::Version
|
192
201
|
version: '2.1'
|
202
|
+
- - ">="
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: 2.1.0
|
193
205
|
type: :runtime
|
194
206
|
prerelease: false
|
195
207
|
version_requirements: !ruby/object:Gem::Requirement
|
196
208
|
requirements:
|
197
|
-
- - ">="
|
198
|
-
- !ruby/object:Gem::Version
|
199
|
-
version: 2.1.0
|
200
209
|
- - "~>"
|
201
210
|
- !ruby/object:Gem::Version
|
202
211
|
version: '2.1'
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: 2.1.0
|
203
215
|
description: A Ruby gem to verify the signature of Firebase ID Tokens. It uses Redis
|
204
216
|
to store Google's x509 certificates and manage their expiration time, so you don't
|
205
217
|
need to request Google's API in every execution and can access it as fast as reading
|
@@ -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,21 +234,33 @@ 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
|
231
246
|
- lib/firebase_id_token/signature.rb
|
232
247
|
- lib/firebase_id_token/testing/certificates.rb
|
233
248
|
- lib/firebase_id_token/version.rb
|
249
|
+
- spec/firebase_id_token/certificates_spec.rb
|
250
|
+
- spec/firebase_id_token/configuration_spec.rb
|
251
|
+
- spec/firebase_id_token/signature_spec.rb
|
252
|
+
- spec/firebase_id_token/signature_test_spec.rb
|
253
|
+
- spec/firebase_id_token_spec.rb
|
254
|
+
- spec/fixtures/files/.about_payload_file
|
255
|
+
- spec/fixtures/files/certificates.json
|
256
|
+
- spec/fixtures/files/jwt.json
|
257
|
+
- spec/fixtures/files/payload.json
|
258
|
+
- spec/spec_helper.rb
|
234
259
|
homepage: https://github.com/fschuindt/firebase_id_token
|
235
260
|
licenses:
|
236
261
|
- MIT
|
237
262
|
metadata: {}
|
238
|
-
post_install_message:
|
263
|
+
post_install_message:
|
239
264
|
rdoc_options: []
|
240
265
|
require_paths:
|
241
266
|
- lib
|
@@ -250,8 +275,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
250
275
|
- !ruby/object:Gem::Version
|
251
276
|
version: '0'
|
252
277
|
requirements: []
|
253
|
-
rubygems_version: 3.
|
254
|
-
signing_key:
|
278
|
+
rubygems_version: 3.1.4
|
279
|
+
signing_key:
|
255
280
|
specification_version: 4
|
256
281
|
summary: A Firebase ID Token verifier.
|
257
282
|
test_files: []
|