firebase_id_token 2.3.0 → 2.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +280 -211
- data/firebase_id_token.gemspec +39 -38
- data/lib/firebase_id_token.rb +20 -1
- data/lib/firebase_id_token/configuration.rb +4 -1
- data/lib/firebase_id_token/signature.rb +5 -1
- data/lib/firebase_id_token/testing/certificates.rb +85 -0
- data/lib/firebase_id_token/version.rb +3 -3
- metadata +40 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 536ac169a34db614f7501d80d974dbd9048a917bb3c0887b6e16f90381772b61
|
4
|
+
data.tar.gz: 83e7a5258af798b479f1a9eea253e4d0dfae6cac5aa0f003787973abb87dc28d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e721876bcfa5f946236d42461bae05365adbfe61c37fd744029fc1e2b27b3c1fe22bc20bf850a6a23fbd18d4e45f2a2572190a76fc86ef5ad022f689ace8d6a
|
7
|
+
data.tar.gz: d06b0c0f60dc2dfe15762ba19fc9ef9549f3efcd46bc124ab0572ba992993fdd06cfd59a3aea8c0708d56916eba3551dade16026ee57fa7ddd1fe103fbf48d5c
|
data/README.md
CHANGED
@@ -1,211 +1,280 @@
|
|
1
|
-
# Ruby Firebase ID Token verifier (pre-release)
|
2
|
-
|
3
|
-
![Alt text](https://api.travis-ci.org/fschuindt/firebase_id_token.svg?branch=master)
|
4
|
-
[![Code Climate](https://codeclimate.com/github/fschuindt/firebase_id_token/badges/gpa.svg)](https://codeclimate.com/github/fschuindt/firebase_id_token)
|
5
|
-
[![Issue Count](https://codeclimate.com/github/fschuindt/firebase_id_token/badges/issue_count.svg)](https://codeclimate.com/github/fschuindt/firebase_id_token)
|
6
|
-
[![Test Coverage](https://codeclimate.com/github/fschuindt/firebase_id_token/badges/coverage.svg)](https://codeclimate.com/github/fschuindt/firebase_id_token/coverage)
|
7
|
-
[![Inline docs](http://inch-ci.org/github/fschuindt/firebase_id_token.svg?branch=master)](http://inch-ci.org/github/fschuindt/firebase_id_token)
|
8
|
-
|
9
|
-
A Ruby gem to verify the signature of Firebase ID Tokens. It uses Redis to store Google's x509 certificates and manage their expiration time, so you don't need to request Google's API in every execution and can access it as fast as reading from memory.
|
10
|
-
|
11
|
-
It also checks the JWT payload parameters as recommended [here](https://firebase.google.com/docs/auth/admin/verify-id-tokens) by Firebase official documentation.
|
12
|
-
|
13
|
-
Feel free to open any issue or to [contact me](https://fschuindt.github.io/blog/about/) directly.
|
14
|
-
Any contribution is welcome.
|
15
|
-
|
16
|
-
## Docs
|
17
|
-
|
18
|
-
+ http://www.rubydoc.info/gems/firebase_id_token
|
19
|
-
|
20
|
-
## Requirements
|
21
|
-
|
22
|
-
+ Redis
|
23
|
-
|
24
|
-
## Installing
|
25
|
-
|
26
|
-
```
|
27
|
-
gem install firebase_id_token
|
28
|
-
```
|
29
|
-
|
30
|
-
or in your Gemfile
|
31
|
-
```
|
32
|
-
gem 'firebase_id_token', '~> 2.3.
|
33
|
-
```
|
34
|
-
then
|
35
|
-
```
|
36
|
-
bundle install
|
37
|
-
```
|
38
|
-
|
39
|
-
## Configuration
|
40
|
-
|
41
|
-
It's needed to set up your Firebase Project ID.
|
42
|
-
|
43
|
-
If you are using Rails, this should probably go into `config/initializers/firebase_id_token.rb`.
|
44
|
-
```ruby
|
45
|
-
FirebaseIdToken.configure do |config|
|
46
|
-
config.project_ids = ['your-firebase-project-id']
|
47
|
-
end
|
48
|
-
```
|
49
|
-
|
50
|
-
`project_ids` must be a Array.
|
51
|
-
|
52
|
-
*If you want to verify signatures from more than one Firebase project, just add more Project IDs to the list.*
|
53
|
-
|
54
|
-
You can also pass a Redis instance to `config` if you are not using Redis defaults.
|
55
|
-
In this case, you must have the gem `redis` in your `Gemfile`.
|
56
|
-
```ruby
|
57
|
-
FirebaseIdToken.configure do |config|
|
58
|
-
config.project_ids = ['your-firebase-project-id']
|
59
|
-
config.redis = Redis.new(host: '10.0.1.1', port: 6380, db: 15)
|
60
|
-
end
|
61
|
-
```
|
62
|
-
|
63
|
-
Otherwise, it will use just `Redis.new` as the instance.
|
64
|
-
|
65
|
-
## Usage
|
66
|
-
|
67
|
-
You can get a glimpse of it by reading our RSpec output on your machine. It's
|
68
|
-
really helpful. But here is a complete guide:
|
69
|
-
|
70
|
-
### Downloading Certificates
|
71
|
-
|
72
|
-
Before verifying tokens, you need to download Google's x509 certificates.
|
73
|
-
|
74
|
-
To do it simply:
|
75
|
-
```ruby
|
76
|
-
FirebaseIdToken::Certificates.request
|
77
|
-
```
|
78
|
-
|
79
|
-
It will download the certificates and save it in Redis, but only if Redis certificates database is empty. To force download and override Redis database, use:
|
80
|
-
```ruby
|
81
|
-
FirebaseIdToken::Certificates.request!
|
82
|
-
```
|
83
|
-
|
84
|
-
Google give us information about the certificates expiration time, it's used to set a Redis TTL (Time-To-Live) when saving it. By doing so, the certificates will be automatically deleted after its expiration.
|
85
|
-
|
86
|
-
#### Certificates Info
|
87
|
-
|
88
|
-
Checks the presence of certificates in Redis database.
|
89
|
-
```ruby
|
90
|
-
FirebaseIdToken::Certificates.present?
|
91
|
-
=> true
|
92
|
-
```
|
93
|
-
|
94
|
-
How many seconds until the certificate's expiration.
|
95
|
-
```ruby
|
96
|
-
FirebaseIdToken::Certificates.ttl
|
97
|
-
=> 22352
|
98
|
-
```
|
99
|
-
|
100
|
-
Lists all certificates in a database.
|
101
|
-
```ruby
|
102
|
-
FirebaseIdToken::Certificates.all
|
103
|
-
=> [{"ec8f292sd30224afac5c55540df66d1f999d" => <OpenSSL::X509::Certificate: [...]]
|
104
|
-
```
|
105
|
-
|
106
|
-
Finds the respective certificate of a given Key ID.
|
107
|
-
```ruby
|
108
|
-
FirebaseIdToken::Certificates.find('ec8f292sd30224afac5c55540df66d1f999d')
|
109
|
-
=> <OpenSSL::X509::Certificate: subject=<OpenSSL::X509 [...]>
|
110
|
-
```
|
111
|
-
|
112
|
-
#### Downloading in Rails
|
113
|
-
|
114
|
-
If you are using Rails, it's clever to download certificates in a cron task, you can use [whenever](https://github.com/javan/whenever).
|
115
|
-
|
116
|
-
**Example**
|
117
|
-
|
118
|
-
*Read whenever's guide on how to set it up.*
|
119
|
-
|
120
|
-
Create your task in `lib/tasks/firebase.rake`:
|
121
|
-
```ruby
|
122
|
-
namespace :firebase do
|
123
|
-
namespace :certificates do
|
124
|
-
desc "Request Google's x509 certificates when Redis is empty"
|
125
|
-
task request: :environment do
|
126
|
-
FirebaseIdToken::Certificates.request
|
127
|
-
end
|
128
|
-
|
129
|
-
desc "Request Google's x509 certificates and override Redis"
|
130
|
-
task force_request: :environment do
|
131
|
-
FirebaseIdToken::Certificates.request!
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
```
|
136
|
-
|
137
|
-
And in your `config/schedule.rb` you might have:
|
138
|
-
```ruby
|
139
|
-
every 1.hour do
|
140
|
-
rake 'firebase:certificates:force_request'
|
141
|
-
end
|
142
|
-
```
|
143
|
-
|
144
|
-
Then:
|
145
|
-
```
|
146
|
-
$ whenever --update-crontab
|
147
|
-
```
|
148
|
-
|
149
|
-
I recommend running it once every hour or every 30 minutes, it's up to you. Normally the certificates expiration time is around 4 to 6 hours, but it's good to perform it in a small fraction of this time.
|
150
|
-
|
151
|
-
When developing, you should just run the task:
|
152
|
-
```
|
153
|
-
$ rake firebase:certificates:request
|
154
|
-
```
|
155
|
-
|
156
|
-
*And remember, you need the Redis server to be running.*
|
157
|
-
|
158
|
-
### Verifying Tokens
|
159
|
-
|
160
|
-
Pass the Firebase ID Token to `FirebaseIdToken::Signature.verify` and it will return the token payload if everything is ok:
|
161
|
-
|
162
|
-
```ruby
|
163
|
-
FirebaseIdToken::Signature.verify(token)
|
164
|
-
=> {"iss"=>"https://securetoken.google.com/firebase-id-token", "name"=>"Bob Test", [...]}
|
165
|
-
```
|
166
|
-
|
167
|
-
When either the signature is false or the token is invalid, it will return `nil`:
|
168
|
-
```ruby
|
169
|
-
FirebaseIdToken::Signature.verify(fake_token)
|
170
|
-
=> nil
|
171
|
-
|
172
|
-
FirebaseIdToken::Signature.verify('aaaaaa')
|
173
|
-
=> nil
|
174
|
-
```
|
175
|
-
|
176
|
-
**WARNING:** If you try to verify a signature without any certificates in Redis database it will raise a `FirebaseIdToken::Exceptions::NoCertificatesError`.
|
177
|
-
|
178
|
-
#### Payload Structure
|
179
|
-
|
180
|
-
In case you need, here's a example of the payload structure from a Google login in JSON.
|
181
|
-
```json
|
182
|
-
{
|
183
|
-
"iss":"https://securetoken.google.com/firebase-id-token",
|
184
|
-
"name":"Ugly Bob",
|
185
|
-
"picture":"https://someurl.com/photo.jpg",
|
186
|
-
"aud":"firebase-id-token",
|
187
|
-
"auth_time":1492981192,
|
188
|
-
"user_id":"theUserID",
|
189
|
-
"sub":"theUserID",
|
190
|
-
"iat":1492981200,
|
191
|
-
"exp":33029000017,
|
192
|
-
"email":"uglybob@emailurl.com",
|
193
|
-
"email_verified":true,
|
194
|
-
"firebase":{
|
195
|
-
"identities":{
|
196
|
-
"google.com":[
|
197
|
-
"1010101010101010101"
|
198
|
-
],
|
199
|
-
"email":[
|
200
|
-
"uglybob@emailurl.com"
|
201
|
-
]
|
202
|
-
},
|
203
|
-
"sign_in_provider":"google.com"
|
204
|
-
}
|
205
|
-
}
|
206
|
-
|
207
|
-
```
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
The
|
1
|
+
# Ruby Firebase ID Token verifier (pre-release)
|
2
|
+
|
3
|
+
![Alt text](https://api.travis-ci.org/fschuindt/firebase_id_token.svg?branch=master)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/fschuindt/firebase_id_token/badges/gpa.svg)](https://codeclimate.com/github/fschuindt/firebase_id_token)
|
5
|
+
[![Issue Count](https://codeclimate.com/github/fschuindt/firebase_id_token/badges/issue_count.svg)](https://codeclimate.com/github/fschuindt/firebase_id_token)
|
6
|
+
[![Test Coverage](https://codeclimate.com/github/fschuindt/firebase_id_token/badges/coverage.svg)](https://codeclimate.com/github/fschuindt/firebase_id_token/coverage)
|
7
|
+
[![Inline docs](http://inch-ci.org/github/fschuindt/firebase_id_token.svg?branch=master)](http://inch-ci.org/github/fschuindt/firebase_id_token)
|
8
|
+
|
9
|
+
A Ruby gem to verify the signature of Firebase ID Tokens. It uses Redis to store Google's x509 certificates and manage their expiration time, so you don't need to request Google's API in every execution and can access it as fast as reading from memory.
|
10
|
+
|
11
|
+
It also checks the JWT payload parameters as recommended [here](https://firebase.google.com/docs/auth/admin/verify-id-tokens) by Firebase official documentation.
|
12
|
+
|
13
|
+
Feel free to open any issue or to [contact me](https://fschuindt.github.io/blog/about/) directly.
|
14
|
+
Any contribution is welcome.
|
15
|
+
|
16
|
+
## Docs
|
17
|
+
|
18
|
+
+ http://www.rubydoc.info/gems/firebase_id_token
|
19
|
+
|
20
|
+
## Requirements
|
21
|
+
|
22
|
+
+ Redis
|
23
|
+
|
24
|
+
## Installing
|
25
|
+
|
26
|
+
```
|
27
|
+
gem install firebase_id_token
|
28
|
+
```
|
29
|
+
|
30
|
+
or in your Gemfile
|
31
|
+
```
|
32
|
+
gem 'firebase_id_token', '~> 2.3.1'
|
33
|
+
```
|
34
|
+
then
|
35
|
+
```
|
36
|
+
bundle install
|
37
|
+
```
|
38
|
+
|
39
|
+
## Configuration
|
40
|
+
|
41
|
+
It's needed to set up your Firebase Project ID.
|
42
|
+
|
43
|
+
If you are using Rails, this should probably go into `config/initializers/firebase_id_token.rb`.
|
44
|
+
```ruby
|
45
|
+
FirebaseIdToken.configure do |config|
|
46
|
+
config.project_ids = ['your-firebase-project-id']
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
`project_ids` must be a Array.
|
51
|
+
|
52
|
+
*If you want to verify signatures from more than one Firebase project, just add more Project IDs to the list.*
|
53
|
+
|
54
|
+
You can also pass a Redis instance to `config` if you are not using Redis defaults.
|
55
|
+
In this case, you must have the gem `redis` in your `Gemfile`.
|
56
|
+
```ruby
|
57
|
+
FirebaseIdToken.configure do |config|
|
58
|
+
config.project_ids = ['your-firebase-project-id']
|
59
|
+
config.redis = Redis.new(host: '10.0.1.1', port: 6380, db: 15)
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
Otherwise, it will use just `Redis.new` as the instance.
|
64
|
+
|
65
|
+
## Usage
|
66
|
+
|
67
|
+
You can get a glimpse of it by reading our RSpec output on your machine. It's
|
68
|
+
really helpful. But here is a complete guide:
|
69
|
+
|
70
|
+
### Downloading Certificates
|
71
|
+
|
72
|
+
Before verifying tokens, you need to download Google's x509 certificates.
|
73
|
+
|
74
|
+
To do it simply:
|
75
|
+
```ruby
|
76
|
+
FirebaseIdToken::Certificates.request
|
77
|
+
```
|
78
|
+
|
79
|
+
It will download the certificates and save it in Redis, but only if Redis certificates database is empty. To force download and override Redis database, use:
|
80
|
+
```ruby
|
81
|
+
FirebaseIdToken::Certificates.request!
|
82
|
+
```
|
83
|
+
|
84
|
+
Google give us information about the certificates expiration time, it's used to set a Redis TTL (Time-To-Live) when saving it. By doing so, the certificates will be automatically deleted after its expiration.
|
85
|
+
|
86
|
+
#### Certificates Info
|
87
|
+
|
88
|
+
Checks the presence of certificates in Redis database.
|
89
|
+
```ruby
|
90
|
+
FirebaseIdToken::Certificates.present?
|
91
|
+
=> true
|
92
|
+
```
|
93
|
+
|
94
|
+
How many seconds until the certificate's expiration.
|
95
|
+
```ruby
|
96
|
+
FirebaseIdToken::Certificates.ttl
|
97
|
+
=> 22352
|
98
|
+
```
|
99
|
+
|
100
|
+
Lists all certificates in a database.
|
101
|
+
```ruby
|
102
|
+
FirebaseIdToken::Certificates.all
|
103
|
+
=> [{"ec8f292sd30224afac5c55540df66d1f999d" => <OpenSSL::X509::Certificate: [...]]
|
104
|
+
```
|
105
|
+
|
106
|
+
Finds the respective certificate of a given Key ID.
|
107
|
+
```ruby
|
108
|
+
FirebaseIdToken::Certificates.find('ec8f292sd30224afac5c55540df66d1f999d')
|
109
|
+
=> <OpenSSL::X509::Certificate: subject=<OpenSSL::X509 [...]>
|
110
|
+
```
|
111
|
+
|
112
|
+
#### Downloading in Rails
|
113
|
+
|
114
|
+
If you are using Rails, it's clever to download certificates in a cron task, you can use [whenever](https://github.com/javan/whenever).
|
115
|
+
|
116
|
+
**Example**
|
117
|
+
|
118
|
+
*Read whenever's guide on how to set it up.*
|
119
|
+
|
120
|
+
Create your task in `lib/tasks/firebase.rake`:
|
121
|
+
```ruby
|
122
|
+
namespace :firebase do
|
123
|
+
namespace :certificates do
|
124
|
+
desc "Request Google's x509 certificates when Redis is empty"
|
125
|
+
task request: :environment do
|
126
|
+
FirebaseIdToken::Certificates.request
|
127
|
+
end
|
128
|
+
|
129
|
+
desc "Request Google's x509 certificates and override Redis"
|
130
|
+
task force_request: :environment do
|
131
|
+
FirebaseIdToken::Certificates.request!
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
And in your `config/schedule.rb` you might have:
|
138
|
+
```ruby
|
139
|
+
every 1.hour do
|
140
|
+
rake 'firebase:certificates:force_request'
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
Then:
|
145
|
+
```
|
146
|
+
$ whenever --update-crontab
|
147
|
+
```
|
148
|
+
|
149
|
+
I recommend running it once every hour or every 30 minutes, it's up to you. Normally the certificates expiration time is around 4 to 6 hours, but it's good to perform it in a small fraction of this time.
|
150
|
+
|
151
|
+
When developing, you should just run the task:
|
152
|
+
```
|
153
|
+
$ rake firebase:certificates:request
|
154
|
+
```
|
155
|
+
|
156
|
+
*And remember, you need the Redis server to be running.*
|
157
|
+
|
158
|
+
### Verifying Tokens
|
159
|
+
|
160
|
+
Pass the Firebase ID Token to `FirebaseIdToken::Signature.verify` and it will return the token payload if everything is ok:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
FirebaseIdToken::Signature.verify(token)
|
164
|
+
=> {"iss"=>"https://securetoken.google.com/firebase-id-token", "name"=>"Bob Test", [...]}
|
165
|
+
```
|
166
|
+
|
167
|
+
When either the signature is false or the token is invalid, it will return `nil`:
|
168
|
+
```ruby
|
169
|
+
FirebaseIdToken::Signature.verify(fake_token)
|
170
|
+
=> nil
|
171
|
+
|
172
|
+
FirebaseIdToken::Signature.verify('aaaaaa')
|
173
|
+
=> nil
|
174
|
+
```
|
175
|
+
|
176
|
+
**WARNING:** If you try to verify a signature without any certificates in Redis database it will raise a `FirebaseIdToken::Exceptions::NoCertificatesError`.
|
177
|
+
|
178
|
+
#### Payload Structure
|
179
|
+
|
180
|
+
In case you need, here's a example of the payload structure from a Google login in JSON.
|
181
|
+
```json
|
182
|
+
{
|
183
|
+
"iss":"https://securetoken.google.com/firebase-id-token",
|
184
|
+
"name":"Ugly Bob",
|
185
|
+
"picture":"https://someurl.com/photo.jpg",
|
186
|
+
"aud":"firebase-id-token",
|
187
|
+
"auth_time":1492981192,
|
188
|
+
"user_id":"theUserID",
|
189
|
+
"sub":"theUserID",
|
190
|
+
"iat":1492981200,
|
191
|
+
"exp":33029000017,
|
192
|
+
"email":"uglybob@emailurl.com",
|
193
|
+
"email_verified":true,
|
194
|
+
"firebase":{
|
195
|
+
"identities":{
|
196
|
+
"google.com":[
|
197
|
+
"1010101010101010101"
|
198
|
+
],
|
199
|
+
"email":[
|
200
|
+
"uglybob@emailurl.com"
|
201
|
+
]
|
202
|
+
},
|
203
|
+
"sign_in_provider":"google.com"
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
```
|
208
|
+
|
209
|
+
|
210
|
+
## Development
|
211
|
+
The test suite can be run with `bundle exec rake rspec`
|
212
|
+
|
213
|
+
|
214
|
+
The test mode is prepared as preparation for the test.
|
215
|
+
|
216
|
+
`FirebaseIdToken.test!`
|
217
|
+
|
218
|
+
|
219
|
+
By using test mode, the following methods become available.
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
# RSA PRIVATE KEY
|
223
|
+
FirebaseIdToken::Testing::Certificates.private_key
|
224
|
+
# CERTIFICATE
|
225
|
+
FirebaseIdToken::Testing::Certificates.certificate
|
226
|
+
```
|
227
|
+
|
228
|
+
CERTIFICATE will always return the same value and will not communicate to google.
|
229
|
+
|
230
|
+
|
231
|
+
### Example
|
232
|
+
#### Rails test
|
233
|
+
|
234
|
+
Describe the following in test_helper.rb etc.
|
235
|
+
|
236
|
+
* test_helper
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
class ActiveSupport::TestCase
|
240
|
+
setup do
|
241
|
+
FirebaseIdToken.test!
|
242
|
+
end
|
243
|
+
end
|
244
|
+
```
|
245
|
+
|
246
|
+
* controller_test
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
require 'test_helper'
|
250
|
+
|
251
|
+
module Api
|
252
|
+
module V1
|
253
|
+
module UsersControllerTest < ActionController::TestCase
|
254
|
+
setup do
|
255
|
+
@routes = Engine.routes
|
256
|
+
@user = users(:one)
|
257
|
+
end
|
258
|
+
|
259
|
+
def create_token(sub: nil)
|
260
|
+
_payload = payload.merge({sub: sub})
|
261
|
+
JWT.encode _payload, OpenSSL::PKey::RSA.new(FirebaseIdToken::Testing::Certificates.private_key), 'RS256'
|
262
|
+
end
|
263
|
+
|
264
|
+
def payload
|
265
|
+
# payload.json
|
266
|
+
end
|
267
|
+
|
268
|
+
test 'should success get api v1 users ' do
|
269
|
+
get :show, headers: create_token(@user.id)
|
270
|
+
assert_response :success
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
```
|
276
|
+
|
277
|
+
|
278
|
+
## License
|
279
|
+
|
280
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/firebase_id_token.gemspec
CHANGED
@@ -1,38 +1,39 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'firebase_id_token/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = 'firebase_id_token'
|
8
|
-
spec.version = FirebaseIdToken::VERSION
|
9
|
-
spec.authors = ['Fernando Schuindt']
|
10
|
-
spec.email = ['f.schuindtcs@gmail.com']
|
11
|
-
|
12
|
-
spec.summary = 'A Firebase ID Token verifier.'
|
13
|
-
spec.description = "A Ruby gem to verify the signature of Firebase ID "\
|
14
|
-
"Tokens. It uses Redis to store Google's x509 certificates and manage "\
|
15
|
-
"their expiration time, so you don't need to request Google's API in "\
|
16
|
-
"every execution and can access it as fast as reading from memory."
|
17
|
-
spec.homepage = 'https://github.com/fschuindt/firebase_id_token'
|
18
|
-
spec.license = 'MIT'
|
19
|
-
|
20
|
-
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
21
|
-
f.match(%r{^(test|spec|features)/})
|
22
|
-
end
|
23
|
-
spec.bindir = 'exe'
|
24
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
|
-
spec.require_paths = ['lib']
|
26
|
-
|
27
|
-
spec.add_development_dependency 'bundler', '~> 1.14'
|
28
|
-
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
30
|
-
spec.add_development_dependency 'redcarpet', '~> 3.4', '>= 3.4.0'
|
31
|
-
spec.add_development_dependency 'simplecov', '~> 0.14.1'
|
32
|
-
spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0', '>= 1.0.0'
|
33
|
-
|
34
|
-
|
35
|
-
spec.add_runtime_dependency 'redis
|
36
|
-
spec.
|
37
|
-
spec.
|
38
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'firebase_id_token/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'firebase_id_token'
|
8
|
+
spec.version = FirebaseIdToken::VERSION
|
9
|
+
spec.authors = ['Fernando Schuindt']
|
10
|
+
spec.email = ['f.schuindtcs@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'A Firebase ID Token verifier.'
|
13
|
+
spec.description = "A Ruby gem to verify the signature of Firebase ID "\
|
14
|
+
"Tokens. It uses Redis to store Google's x509 certificates and manage "\
|
15
|
+
"their expiration time, so you don't need to request Google's API in "\
|
16
|
+
"every execution and can access it as fast as reading from memory."
|
17
|
+
spec.homepage = 'https://github.com/fschuindt/firebase_id_token'
|
18
|
+
spec.license = 'MIT'
|
19
|
+
|
20
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
21
|
+
f.match(%r{^(test|spec|features)/})
|
22
|
+
end
|
23
|
+
spec.bindir = 'exe'
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ['lib']
|
26
|
+
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
28
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
30
|
+
spec.add_development_dependency 'redcarpet', '~> 3.4', '>= 3.4.0'
|
31
|
+
spec.add_development_dependency 'simplecov', '~> 0.14.1'
|
32
|
+
spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0', '>= 1.0.0'
|
33
|
+
spec.add_development_dependency 'pry', '~> 0.12.2'
|
34
|
+
|
35
|
+
spec.add_runtime_dependency 'redis', '~> 4.0', '>= 4.0.1'
|
36
|
+
spec.add_runtime_dependency 'redis-namespace', '~> 1.6', '>= 1.6.0'
|
37
|
+
spec.add_dependency 'httparty', '~> 0.16', '>= 0.16.2'
|
38
|
+
spec.add_runtime_dependency 'jwt', '~> 2.1', '>= 2.1.0'
|
39
|
+
end
|
data/lib/firebase_id_token.rb
CHANGED
@@ -19,6 +19,11 @@ require 'firebase_id_token/signature'
|
|
19
19
|
# + {Certificates.ttl}
|
20
20
|
# + {Certificates.find}
|
21
21
|
# + {Signature.verify}
|
22
|
+
# + {FirebaseIdToken.test!}
|
23
|
+
# + {Testing::Certificates.private_key}
|
24
|
+
# + {Testing::Certificates.find}
|
25
|
+
# + {Testing::Certificates.private_key}
|
26
|
+
# + {Testing::Certificates.certificate}
|
22
27
|
#
|
23
28
|
# ## Configuration
|
24
29
|
#
|
@@ -44,7 +49,7 @@ module FirebaseIdToken
|
|
44
49
|
|
45
50
|
def self.configuration
|
46
51
|
@configuration ||= Configuration.new
|
47
|
-
end
|
52
|
+
end
|
48
53
|
|
49
54
|
# Resets Configuration to defaults.
|
50
55
|
def self.reset
|
@@ -54,4 +59,18 @@ module FirebaseIdToken
|
|
54
59
|
def self.configure
|
55
60
|
yield configuration
|
56
61
|
end
|
62
|
+
|
63
|
+
# Method for starting test mode.
|
64
|
+
# You can verify with a test certificate or you can use a test private key to verify the token.
|
65
|
+
# When using, write it at the beginning of the test.
|
66
|
+
# @example
|
67
|
+
# class ActiveSupport::TestCase
|
68
|
+
# setup do
|
69
|
+
# FirebaseIdToken.test!
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
def self.test!
|
73
|
+
require 'firebase_id_token/testing/certificates'
|
74
|
+
self.configuration.certificates = FirebaseIdToken::Testing::Certificates
|
75
|
+
end
|
57
76
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module FirebaseIdToken
|
2
2
|
# Handles the configuration object. Check out {FirebaseIdToken} for more
|
3
3
|
# info on how to use it.
|
4
|
+
LIB_PATH = File.expand_path('../../', __FILE__)
|
5
|
+
|
4
6
|
class Configuration
|
5
|
-
attr_accessor :redis, :project_ids
|
7
|
+
attr_accessor :redis, :project_ids, :certificates
|
6
8
|
|
7
9
|
def initialize
|
8
10
|
@redis = Redis.new
|
9
11
|
@project_ids = []
|
12
|
+
@certificates = FirebaseIdToken::Certificates
|
10
13
|
end
|
11
14
|
end
|
12
15
|
end
|
@@ -47,6 +47,8 @@ module FirebaseIdToken
|
|
47
47
|
new(jwt_token).verify
|
48
48
|
end
|
49
49
|
|
50
|
+
attr_accessor :firebase_id_token_certificates
|
51
|
+
|
50
52
|
# Loads attributes: `:project_ids` from {FirebaseIdToken::Configuration},
|
51
53
|
# and `:kid`, `:jwt_token` from the related `jwt_token`.
|
52
54
|
# @param [String] jwt_token Firebase ID Token
|
@@ -54,11 +56,13 @@ module FirebaseIdToken
|
|
54
56
|
@project_ids = FirebaseIdToken.configuration.project_ids
|
55
57
|
@kid = extract_kid(jwt_token)
|
56
58
|
@jwt_token = jwt_token
|
59
|
+
@firebase_id_token_certificates = FirebaseIdToken.configuration.certificates
|
60
|
+
|
57
61
|
end
|
58
62
|
|
59
63
|
# @see Signature.verify
|
60
64
|
def verify
|
61
|
-
certificate =
|
65
|
+
certificate = firebase_id_token_certificates.find(@kid)
|
62
66
|
if certificate
|
63
67
|
payload = decode_jwt_payload(@jwt_token, certificate.public_key)
|
64
68
|
authorize payload
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module FirebaseIdToken
|
2
|
+
module Testing
|
3
|
+
# When executing the test, manage secret key and certificate with Fixture.
|
4
|
+
# Valid for Ruby applications using minitest
|
5
|
+
# ## Access Certificates.
|
6
|
+
# `FirebaseIdToken.test!` is required to start using this class. <br />
|
7
|
+
# When implementing minitest, always return the same certificate.
|
8
|
+
# Provide secret key for encoding JWT.
|
9
|
+
#
|
10
|
+
# ## List of available methods
|
11
|
+
# + {Certificates.find}
|
12
|
+
# + {Certificates.private_key}
|
13
|
+
# + {Certificates.certificate}
|
14
|
+
class Certificates
|
15
|
+
# `.find` is stabbed to always return the same certificate.
|
16
|
+
# @param [String] kid Key ID
|
17
|
+
# @return [nil, OpenSSL::X509::Certificate]
|
18
|
+
def self.find(kid)
|
19
|
+
cert = certificate
|
20
|
+
OpenSSL::X509::Certificate.new cert
|
21
|
+
end
|
22
|
+
|
23
|
+
# Return the secret key defined by Fixture.
|
24
|
+
# @return [string]
|
25
|
+
# @example `.private_kay`
|
26
|
+
# '-----BEGIN RSA PRIVATE KEY-----
|
27
|
+
# MIICXAIBAAKBgQCrvJRW05yKQxx3+PdiysRKR/N+VqYv9+b/76C3zC/vk9ACkWTN
|
28
|
+
# /dcPMzIXVIdDMU+r1o8HF3mOXNhCFWGSfZ7r1dMe961BQtxu1DagC7Ff+XZZL0Mu
|
29
|
+
# 0W0Y/GmP7yTrsie7wCq4QiHj2HBtUtze/uC6DT8Qcthg46LUJBqeh9FiIwIDAQAB
|
30
|
+
# AoGAEGK80I/+Np7yn2vMxstL8T5uOBayYo9HphHKBt9fj39N8IDI2nKmy1d6Jwm0
|
31
|
+
# oi+ZR28AVI/j1DZ9l8iMd7qup+/D5CdTt89u8fTUlQkCjAQQsRBneq5MJRKI+5eA
|
32
|
+
# JDJmx7p7CUUqjnIcFfbBz0NLTDZso11Vp+BDfbDpKv37nskCQQDZimWuxa7rK6UZ
|
33
|
+
# XGDl8LxEiM27US67kDu8iS3VdQWEKIhhQoea/zNKPMkQsc2+CPggQTcG/2WuPEYJ
|
34
|
+
# O1bPz7HPAkEAyhknhziWREEBQRLp4qsakozMIn4iuuaC00zpLwcnyOqFPaHS5CTL
|
35
|
+
# I7GxpwN6Ld1N/nqvYGyk/dRb5Ul7v27DbQJAUMsJwMNCl6z6AFVC16N1CK8WWX9p
|
36
|
+
# L9f9l6QLFcAEcHTtUdH3syUc03GH619d3jpOjQwrd7na9b8E8+DJ+RxWGQJAI8cE
|
37
|
+
# OmoIIBkp8a05fokv8RW/5bNSzqeULXgGJ+8qWeU6pUiKnxzsYWtJuflhndD5x71M
|
38
|
+
# YtOY+d6oThUONTuUmQJBAMGl/eaFU0AfA+xS/3Kt5JFKBbBVAByhL+Hd/27/rYZ5
|
39
|
+
# 8YXDUQAgcykCS21JMrn41p4gwJnpG35PoV8qBIW9a94=
|
40
|
+
# -----END RSA PRIVATE KEY-----'
|
41
|
+
|
42
|
+
def self.private_key
|
43
|
+
@rsa_private ||= jwt_json['private_key']
|
44
|
+
end
|
45
|
+
|
46
|
+
# Return the certificate defined by Fixture.
|
47
|
+
# @return [string]
|
48
|
+
# @example `.certificate`
|
49
|
+
# -----BEGIN CERTIFICATE-----
|
50
|
+
# MIIChDCCAe2gAwIBAgIBADANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJCRTEN
|
51
|
+
# MAsGA1UECgwEVGVzdDENMAsGA1UECwwEVGVzdDENMAsGA1UEAwwEVGVzdDAgFw0x
|
52
|
+
# NzA0MjQwMjE5MzRaGA8zMDE2MDgyNTAyMTkzNFowOjELMAkGA1UEBhMCQkUxDTAL
|
53
|
+
# BgNVBAoMBFRlc3QxDTALBgNVBAsMBFRlc3QxDTALBgNVBAMMBFRlc3QwgZ8wDQYJ
|
54
|
+
# KoZIhvcNAQEBBQADgY0AMIGJAoGBAKu8lFbTnIpDHHf492LKxEpH835Wpi/35v/v
|
55
|
+
# oLfML++T0AKRZM391w8zMhdUh0MxT6vWjwcXeY5c2EIVYZJ9nuvV0x73rUFC3G7U
|
56
|
+
# NqALsV/5dlkvQy7RbRj8aY/vJOuyJ7vAKrhCIePYcG1S3N7+4LoNPxBy2GDjotQk
|
57
|
+
# Gp6H0WIjAgMBAAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUFKl2
|
58
|
+
# nZaaeNZM/7dno9IbaEIvaXQwYgYDVR0jBFswWYAUFKl2nZaaeNZM/7dno9IbaEIv
|
59
|
+
# aXShPqQ8MDoxCzAJBgNVBAYTAkJFMQ0wCwYDVQQKDARUZXN0MQ0wCwYDVQQLDARU
|
60
|
+
# ZXN0MQ0wCwYDVQQDDARUZXN0ggEAMA0GCSqGSIb3DQEBBQUAA4GBAKkBvhUIRENB
|
61
|
+
# ap0r9F7sKkRr8tJCCjBPIA+8e8XIKS3A3w6EI5ErRpv795rO80TBR4WZR9GhH8M1
|
62
|
+
# PXJ7FuaayCcPAl0febjl4z6ZciCSDpBdhbMpmq1d/kYU1H1qUokE2BxhNdcs/Q4w
|
63
|
+
# +5NnFGSkYm09tPzLWFPLoES9ynBF0N7l
|
64
|
+
# -----END CERTIFICATE-----
|
65
|
+
#
|
66
|
+
def self.certificate
|
67
|
+
@certs ||= jwt_json['certificate']
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def self.jwt_json
|
73
|
+
@jwt_json ||= JSON.parse read_jwt_file
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.read_jwt_file
|
77
|
+
File.read(
|
78
|
+
File.expand_path(
|
79
|
+
File.join(FirebaseIdToken::LIB_PATH, '..', 'spec', 'fixtures', 'files', 'jwt.json')
|
80
|
+
)
|
81
|
+
)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
module FirebaseIdToken
|
2
|
-
VERSION = '2.3.
|
3
|
-
end
|
1
|
+
module FirebaseIdToken
|
2
|
+
VERSION = '2.3.1'
|
3
|
+
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.3.
|
4
|
+
version: 2.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fernando Schuindt
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -56,22 +56,22 @@ dependencies:
|
|
56
56
|
name: redcarpet
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '3.4'
|
62
59
|
- - ">="
|
63
60
|
- !ruby/object:Gem::Version
|
64
61
|
version: 3.4.0
|
62
|
+
- - "~>"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '3.4'
|
65
65
|
type: :development
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
68
68
|
requirements:
|
69
|
-
- - "~>"
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
version: '3.4'
|
72
69
|
- - ">="
|
73
70
|
- !ruby/object:Gem::Version
|
74
71
|
version: 3.4.0
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.4'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: simplecov
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,22 +90,36 @@ dependencies:
|
|
90
90
|
name: codeclimate-test-reporter
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 1.0.0
|
93
96
|
- - "~>"
|
94
97
|
- !ruby/object:Gem::Version
|
95
98
|
version: '1.0'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
96
103
|
- - ">="
|
97
104
|
- !ruby/object:Gem::Version
|
98
105
|
version: 1.0.0
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '1.0'
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: pry
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: 0.12.2
|
99
116
|
type: :development
|
100
117
|
prerelease: false
|
101
118
|
version_requirements: !ruby/object:Gem::Requirement
|
102
119
|
requirements:
|
103
120
|
- - "~>"
|
104
121
|
- !ruby/object:Gem::Version
|
105
|
-
version:
|
106
|
-
- - ">="
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
version: 1.0.0
|
122
|
+
version: 0.12.2
|
109
123
|
- !ruby/object:Gem::Dependency
|
110
124
|
name: redis
|
111
125
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,22 +144,22 @@ dependencies:
|
|
130
144
|
name: redis-namespace
|
131
145
|
requirement: !ruby/object:Gem::Requirement
|
132
146
|
requirements:
|
133
|
-
- - "~>"
|
134
|
-
- !ruby/object:Gem::Version
|
135
|
-
version: '1.6'
|
136
147
|
- - ">="
|
137
148
|
- !ruby/object:Gem::Version
|
138
149
|
version: 1.6.0
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '1.6'
|
139
153
|
type: :runtime
|
140
154
|
prerelease: false
|
141
155
|
version_requirements: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
|
-
- - "~>"
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: '1.6'
|
146
157
|
- - ">="
|
147
158
|
- !ruby/object:Gem::Version
|
148
159
|
version: 1.6.0
|
160
|
+
- - "~>"
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '1.6'
|
149
163
|
- !ruby/object:Gem::Dependency
|
150
164
|
name: httparty
|
151
165
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,22 +184,22 @@ dependencies:
|
|
170
184
|
name: jwt
|
171
185
|
requirement: !ruby/object:Gem::Requirement
|
172
186
|
requirements:
|
173
|
-
- - "~>"
|
174
|
-
- !ruby/object:Gem::Version
|
175
|
-
version: '2.1'
|
176
187
|
- - ">="
|
177
188
|
- !ruby/object:Gem::Version
|
178
189
|
version: 2.1.0
|
190
|
+
- - "~>"
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '2.1'
|
179
193
|
type: :runtime
|
180
194
|
prerelease: false
|
181
195
|
version_requirements: !ruby/object:Gem::Requirement
|
182
196
|
requirements:
|
183
|
-
- - "~>"
|
184
|
-
- !ruby/object:Gem::Version
|
185
|
-
version: '2.1'
|
186
197
|
- - ">="
|
187
198
|
- !ruby/object:Gem::Version
|
188
199
|
version: 2.1.0
|
200
|
+
- - "~>"
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: '2.1'
|
189
203
|
description: A Ruby gem to verify the signature of Firebase ID Tokens. It uses Redis
|
190
204
|
to store Google's x509 certificates and manage their expiration time, so you don't
|
191
205
|
need to request Google's API in every execution and can access it as fast as reading
|
@@ -215,6 +229,7 @@ files:
|
|
215
229
|
- lib/firebase_id_token/exceptions/certificates_ttl_error.rb
|
216
230
|
- lib/firebase_id_token/exceptions/no_certificates_error.rb
|
217
231
|
- lib/firebase_id_token/signature.rb
|
232
|
+
- lib/firebase_id_token/testing/certificates.rb
|
218
233
|
- lib/firebase_id_token/version.rb
|
219
234
|
homepage: https://github.com/fschuindt/firebase_id_token
|
220
235
|
licenses:
|
@@ -235,8 +250,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
235
250
|
- !ruby/object:Gem::Version
|
236
251
|
version: '0'
|
237
252
|
requirements: []
|
238
|
-
|
239
|
-
rubygems_version: 2.6.14
|
253
|
+
rubygems_version: 3.0.3
|
240
254
|
signing_key:
|
241
255
|
specification_version: 4
|
242
256
|
summary: A Firebase ID Token verifier.
|