23 years developing web; 14 professionaly, 7 with Elixir.
Profile: https://fschuindt.722.network/about/
Blog: https://fschuindt.722.network/
A Ruby gem to verify the signature of Firebase ID Tokens.
License: MIT License
23 years developing web; 14 professionaly, 7 with Elixir.
Profile: https://fschuindt.722.network/about/
Blog: https://fschuindt.722.network/
Cannot use redis_cache_store option with your gem,
Is there a way to you update your redis requirements to 4?
Thanks
Using this library, newly issued tokens don't verify correctly until one second after they have been issued.
Found using a client example which did a forceRefresh on the token every time - had a timing dependent bug where these tokens sometimes verified OK but mostly didn't.
def still_valid?(payload)
payload['exp'].to_i > Time.now.to_i &&
payload['iat'].to_i < Time.now.to_i
end
Should be payload['iat'].to_i <= Time.now.to_i
The Admin SDKs use an environment flag
I can take a crack it after I take a look at admin sdk source implementation.
Helpful details firebase/firebase-tools#2764
I was messing around with the gem and it seems like it'd be pretty easy to use Rails.cache.fetch to pull in the new certs if they're expired.
I see a few pros and cons:
Pros:
Cons:
Hi! Thanks for the gem! I would love to use it but am hesitant to introduce Redis as a dependency just so I can verify Firebase tokens...is there any way I can not use Redis and have the gem work?
my docker couldn't build my app because it doesn't redis locally
it works after I modified configuration file
hungryhub-team@9087203
request!
looks more ruby
-way :) Please, consider the naming
Hi, firstly thanks you for your library. I am working in a rails API that authenticate the users in an Android app using Google and Facebook login and giving a firebase token when the users log in the app. I send this token to the server API and i try to verify the token using the method FirebaseIdToken::Signature.verify(Token) but always returned nil.
I have followed the instructions in the main page of your gitHub project, installing and setting up all the requeriments, but i still have the same problem.
I have been thinking in the possibility that the problem is at the config file (firebase_id_token.rb), because i am not sure if the firebase-project-id its what i think it is.
FirebaseIdToken.configure do |config|
config.project_ids = [myproject-7839d]
end
Getting the firebase-project-id from:
Thanks u a lot for the help.
Getting the following failure when firebase_id_token processes are run.
Using redis 6 Premium tier on Heroku which forces secure TLS connections.
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 peeraddr=52.3.18.23:26249 state=error: certificate verify failed (self signed certificate in certificate chain)
redis.rb configuration file is set to VERIFY_NONE as suggested in heroku documentation
$redis = Redis.new(url: url, driver: :ruby, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE })
Firebase_id_token works when redis is not forcing secure connections.
Full stack
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 peeraddr=52.3.18.23:26249 state=error: certificate verify failed (self signed certificate in certificate chain)
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/connection/ruby.rb:264:in connect_nonblock' /opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/connection/ruby.rb:264:in
connect'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/connection/ruby.rb:306:in connect' /opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/client.rb:385:in
establish_connection'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/client.rb:115:in block in connect' /opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/client.rb:344:in
with_reconnect'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/client.rb:114:in connect' /opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/client.rb:417:in
ensure_connected'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/client.rb:269:in block in process' /opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/client.rb:356:in
logging'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/client.rb:268:in process' /opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/client.rb:161:in
call'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis.rb:270:in block in send_command' /opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis.rb:269:in
synchronize'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis.rb:269:in send_command' /opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-4.8.0/lib/redis/commands/strings.rb:191:in
get'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-namespace-1.10.0/lib/redis/namespace.rb:558:in wrapped_send' /opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-namespace-1.10.0/lib/redis/namespace.rb:515:in
call_with_namespace'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/redis-namespace-1.10.0/lib/redis/namespace.rb:389:in block (2 levels) in <class:Namespace>' /opt/homebrew/lib/ruby/gems/3.1.0/gems/firebase_id_token-2.4.0/lib/firebase_id_token/certificates.rb:181:in
read_certificates'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/firebase_id_token-2.4.0/lib/firebase_id_token/certificates.rb:159:in initialize' /opt/homebrew/lib/ruby/gems/3.1.0/gems/firebase_id_token-2.4.0/lib/firebase_id_token/certificates.rb:66:in
new'
/opt/homebrew/lib/ruby/gems/3.1.0/gems/firebase_id_token-2.4.0/lib/firebase_id_token/certificates.rb:66:in request!' /Users/garrettglover/development/Kidletcare/kidletcare_api/lib/tasks/firebase.rake:10:in
block (3 levels) in
Versions
ruby '3.1.2'
gem 'rails', '> 7.0.3'> 4.2', '>= 4.2.5'
gem 'redis', '
gem 'firebase_id_token', '~> 2.4.0'
Hi,
I have some difficulties to run the tests as expected in the doc.
I have a controller test : domains_controller_test.rb
`
require 'test_helper'
module Api
module V1
class DomainsControllerTest < ActionController::TestCase
setup do
#@routes = Engine.routes
#@user = users(:one)
end
def create_token(sub: nil)
_payload = payload.merge({sub: sub})
JWT.encode _payload, OpenSSL::PKey::RSA.new(FirebaseIdToken::Testing::Certificates.private_key), 'RS256'
end
def payload
# payload.json
end
test 'should success get api v1 users ' do
get :show, headers: create_token(@user.id)
assert_response :success
end
end
end
end`
When I run the test, I have this error
test_should_success_get_api_v1_users_#Api::V1::DomainsControllerTest (0.03s)
NameError: NameError: uninitialized constant Api::V1::DomainsControllerTest::Engine
test/controllers/domains_controller_test.rb:7:in `block in class:DomainsControllerTest
I don't know if it's an error from my rails tests configuration. After some researches on rails Engines and on this type of error on stackoverflow, I didn't found how to figure it out.
It may come from my misunderstanding of some basic Rails stuffs.
Maybe the FirebaseIdToken.test! should init an Engine ?
When I comment the setup of the test case and hard code
get :show, headers: create_token(1)
I get an
ArgumentError: wrong number of arguments (given 1, expected 0)
So I tried
get :show, headers: create_token() NoMethodError: undefined method 'merge' for nil:NilClass
So I am looking for where the payload variable is initialized. I'am stuck there, so I try to have some help to understand what I'am doing wrong.
Thank you for your help.
Emeric
As shown in this image, the test coverage report by Code Climate is "unknown". I don't know what's happening and have little time to investigate at the moment. But I think it's worth to be mentioned here.
Anyone interested into tackling it can use your own Code Climate account, let me know if anything is needed from me.
Thanks for this great gem. It really very helpful for known projects ids. But for dynamic project id(s) this gem is not thread safe. In our case we have so much firebase projects on our database associated spesific users. As a workaround we monkey-patched the gem like the following:
module FirebaseIdToken
def self.configuration
Thread.current[:__fid_configuration] ||= Configuration.new
end
# Resets Configuration to defaults.
def self.reset
Thread.current[:__fid_configuration] = Configuration.new
end
end
With this setup the following code sample is thread safe:
pool = ConnectionPool.new(size: 100) { Redis.new url: ENV['REDIS_URL'] }
Array(0..100).each do |project_id|
Thread.new(project_id) do |project_id|
pool.with do |conn|
FirebaseIdToken.configure do |config|
config.project_ids = [project_id]
config.redis = conn
end
FirebaseIdToken::Certificates.request
FirebaseIdToken::Signature.verify(token)
end
end
end
In our use case this patch worked. If there is alternative approach, it is welcome. Otherwise I can create pull request including this monkey patched code.
I do have valid latest certificates from Google APIs stored in Redis. The above method is throwing the following error.
> JWT.decode(token, cert_key, true, {:algorithm=>"RS256", :verify_iat=> false})
Traceback (most recent call last):
2: from (irb):28
1: from (irb):29:in `rescue in irb_binding'
JWT::VerificationError (Signature verification raised)
I used google sign in flutter library and generated an id token. The decoded ID Token appears similar to following:
{
"name": "Mission Impossible",
"picture": "https://lh3.googleusercontent.com/a-/AzyxwvutsrqponmlkjihgfedcbaZ=s94-12-16c",
"iss": "https://securetoken.google.com/my-app",
"aud": "my-app",
"auth_time": 1620067560,
"user_id": "iDdVVuTsRQppprfHzyxwjkcX383",
"sub": "iDdVVuTsRQppprfHzyxwjkcX383",
"iat": 1620067560,
"exp": 1620071160,
"email": "[email protected]",
"email_verified": true,
"firebase": {
"identities": {
"google.com": [
"106342823543215321"
],
"email": [
"[email protected]"
]
},
"sign_in_provider": "google.com"
}
}
looks like the same structure this library is expecting. any clue why I'm getting an invalid signature error when the library is trying to decode the token?
Hi,
I've been struggling today with the implementation of my tests with rspec, which would not pass even using the FirebaseIdToken.test!
and the pretty cool code snippet explaining how to generate a token in test mode.
In order for the FirebaseIdToken::Signature.verify
method to return a payload, it has to be valid, which implies 4 things to be in order in the test payload that's encrypted for token generation:
iat
timestamp value before the test running timeexp
timestamp value after the test running timeaud
string to contain the project idiss
string to contain a url that depends on the project idThis error is invisible when testing with custom payload that's not a Google-generated token from actual firebase project.
It would be nice to add in the Test section of the documentation something that reminds of those requirements for a valid test payload.
I was wondering if you had any thoughts on this:
def login
sleep(2)
decoded = verify_token(params[:token])
puts(decoded)
json_response(firebase_data: decoded)
end
def verify_token(token)
FirebaseIdToken::Signature.verify(token)
end
^works
def login
decoded = verify_token(params[:token])
puts(decoded)
json_response(firebase_data: decoded)
end
def verify_token(token)
FirebaseIdToken::Signature.verify(token)
end
^ not work :( firebase_data is null
hello.
Before replacing it with another on redis, I realized it was hard to test when using it with Rails.
I'm happy if you merge. 🙇
PR #14
Imagine, you do not want to deal with cron and other periodic schedulers
What about automatically update certificates during single request if ttl <= configured_threshold
To prevent multiple instances to update in parallel it is simple to introduce some Redis-based lock
Add YARD document of PR #17 .
The firabase payload has ['email_verified'],
and I think it should be verified when using tokens in rails app.
It's probably related to my development environment but i'm getting the following error when running FirebaseIdToken::Certificates.request!
Redis::ProtocolError: Got 'H' as initial reply byte. If you're in a forking environment, such as Unicorn, you need to connect to Redis after forking.
Just wondering if you have seen this before? I'll do some more digging
#33 introduced new caching functionality to store certificates in memory. However, it breaks the gem in many ways, because the in-memory caching isn't refreshed when you call request!
, which results in different threads and/or processes having different certificates after request!
.
I'd suggest to rollback the functionality and leave local caching implementation to the applications (since you can't refresh a local cache if the certificates are updated in other process without using a shared storage).
Hi,
Using gem version 2.3.1 I can't use FirebaseIdToken.test!
anymore. It always give me this error:
Errno::ENOENT:
No such file or directory @ rb_sysopen - /home/michel/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/firebase_id_token-2.3.1/spec/fixtures/files/jwt.json
Looking at the files released on 2.3.1 it seems like the folder spec
is really missing:
tar xf firebase_id_token-2.3.1.gem
tar ltf data.tar.gz
.gitignore
.rspec
.travis.yml
.yardopts
CODE_OF_CONDUCT.md
Gemfile
LICENSE.txt
README.md
Rakefile
bin/console
bin/setup
firebase_id_token.gemspec
lib/firebase_id_token.rb
lib/firebase_id_token/certificates.rb
lib/firebase_id_token/configuration.rb
lib/firebase_id_token/exceptions/certificates_request_error.rb
lib/firebase_id_token/exceptions/certificates_ttl_error.rb
lib/firebase_id_token/exceptions/no_certificates_error.rb
lib/firebase_id_token/signature.rb
lib/firebase_id_token/testing/certificates.rb
lib/firebase_id_token/version.rb
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.