Using Firebase Authentication with Ruby on Rails Server

5,086 views
Skip to first unread message

Hiren Mistry

unread,
Aug 1, 2016, 9:27:08 PM8/1/16
to Firebase Google Group
Hi

I have a couple questions regarding Firebase Authentication. I'm exploring the possibility of using it for client side user authentication for access to my server.

1. How can my Server connect to Firebase service and verify client tokens without a Ruby SDK? Or is there a Ruby SDK or REST API I can use? (Client will create and sign in using Firebase Authentication SDK and send the token to the server which the server needs to verify is valid.)

2. Once my Server can connect with Firebase, how can I get a list of Users with their attributes from Firebase Authentication? Is it just "/users" like if it were a data object in Firebase database, e.g. "/animals", or is it something else to prevent naming conflicts with data stored? 

Thanks,

Hiren.



Kato Richardson

unread,
Aug 2, 2016, 1:15:52 PM8/2/16
to Firebase Google Group
Hello Hiren,

Great to meet you! If you want to work in Ruby, then you'll need to pick a suitable Ruby JWT gem, and then you can follow the instructions for verifying tokens using a third party library.

Note: If you're already using the Firebase Database, you probably don't need this. You can simply configure your security rules to verify authentication, have the user write to the secured path, and your server can read the data there. This avoids the need for your server to have a REST API and to verify secure credentials, or to pass around tokens. See firebase-queue for a great implementation of this approach.

☼, Kato

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/cfd00185-38d4-4443-accd-275b9d180ccc%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Kato Richardson | Developer Programs Eng | kato...@google.com | 775-235-8398

Hiren Mistry

unread,
Aug 2, 2016, 4:35:54 PM8/2/16
to Firebase Google Group
Hi Kato

Thanks for your quick response. I looked through the docs and have a question.

1. The client signs in to Firebase Auth and receives an ID token which it sends to my Rails server. The JWT gem decodes the ID token and the server checks the different attributes. If it checks out, the server accepts the token and info as valid and grant access to content. How does the server close the verification loop with Firebase that JWT token is valid for a particular user client?

2. How can my server get user email and name for the ID token from Firebase? (I'm not using Firebase for storing any data)

Thanks,
Hiren.

Kato Richardson

unread,
Aug 2, 2016, 6:25:20 PM8/2/16
to Firebase Google Group
Hello Hiren,

Your server doesn't need to "close the loop" or inform Firebase the token is valid. That is done at the client by using authWithCustomToken(). The sole purpose of the server-side token verification is to provide your code a way to tap into the Firebase auth workflow and to verify a client has valid credentials in place before performing some action on their behalf.

☼, Kato


For more options, visit https://groups.google.com/d/optout.

Hiren Mistry

unread,
Aug 3, 2016, 8:56:34 AM8/3/16
to Firebase Google Group

Hi Kato,

Replying again since it seems my response did not go through.

Yes that's correct, by "close the loop" I mean my server-side token verification and not informing Firebase the token is valid (Firebase generates the token after user logs in). 

So how does my server do server-side token verification with Firebase?

I didn't see an answer to my second question which is -
2. How can my server get user email and name for the ID token from Firebase? (I'm not using Firebase for storing any data)

Thanks,

Hiren



Jacob Wenger

unread,
Aug 3, 2016, 2:19:53 PM8/3/16
to fireba...@googlegroups.com
Hey Hiren,

So how does my server do server-side token verification with Firebase?

You can use the Firebase SDKs (or a third-party JWT library) to verify ID tokens

How can my server get user email and name for the ID token from Firebase? (I'm not using Firebase for storing any data)

If you are minting your own custom tokens, you could store these values in the token itself. Otherwise, you would need to store them somewhere else. The Realtime Database is designed exactly for this use case. Read through our doc on structuring and securing user data.

Once my Server can connect with Firebase, how can I get a list of Users with their attributes from Firebase Authentication? Is it just "/users" like if it were a data object in Firebase database, e.g. "/animals", or is it something else to prevent naming conflicts with data stored? 

We don't currently expose an API for reading your user data stored in Firebase Authentication. One is in the works though and we hope to bring it to you soon. In the meantime, you will need to store this data in the Realtime Database, as mentioned in the last point.

Cheers,
Jacob

Hiren Mistry

unread,
Aug 3, 2016, 3:20:03 PM8/3/16
to Firebase Google Group
Hi Jacob,

Thanks for the answers.

One more question, I'm using Ruby on Rails on my server with a JWT library to verify the tokens. What do I use for the secret to decode the token? It's not clear from the docs.

Hiren.

Jacob Wenger

unread,
Aug 3, 2016, 4:51:25 PM8/3/16
to fireba...@googlegroups.com
Hey Hiren,

JWTs are encoded, not encrypted. You can prove this by posted any Firebase ID token JWT into jwt.io. Any third-party JWT library (e.g. ruby-jwt) should be able to decode a JWT without requiring a secret.

Cheers,
Jacob

Hiren Mistry

unread,
Aug 3, 2016, 6:05:54 PM8/3/16
to Firebase Google Group
Jacob,

Got it. 

What's tripping me is what to put for rsa_public so ruby-jwt will run verification? 

JWT.decode(token, rsa_public, true, { :algorithm => 'RS256' })

Based on my understanding from the docs, I tried the public keys (and corresponding key) from https://www.googleapis.com/robot/v1/metadata/x509/secur...@system.gserviceaccount.com.

Sorry for the 20 questions... new to JWT and this authentication scheme. Almost there... :)

Hiren.

Jacob Wenger

unread,
Aug 3, 2016, 6:34:15 PM8/3/16
to fireba...@googlegroups.com
You are correct that the value for rsa_public should be the full public key string ("-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n") corresponding to the JWT's kid from the URL you posted. If that is not working, please post some code showing what you are trying as well as the error message you are receiving. Without those things, we can only guess at what your problem is.

Jacob

Hiren Mistry

unread,
Aug 5, 2016, 12:34:59 AM8/5/16
to Firebase Google Group
Jacob,

Thank you for your patience in helping me understand the pieces correctly.

Here's what I'm trying out... very simple. 

The error is in the JWT library where it tries to pass a method `verify` to the string I passed as `rsa_public`. I looked through the JWT doc's but there's not mention `rsa_public` should be of some type so I assume its a string based on example.

If I set verification to false, JWT.decode will decode the token and I can see the contents. But I need verification to work so I know its legit.

Hiren.

require 'jwt' # uses version 1.5.4

public_keys
= { ...Hash of the public keys from the googleapis link... }


token
= "....  JWT token ...."
puts JWT
.decode(token, public_keys["correct key value"], true, { algorithm: "RS256", verify_iat: true }) # you can try other verification options, it doesn't matter



Error I get is:
/Users/hm/.rvm/gems/ruby-2.3.0@blah/gems/jwt-1.5.4/lib/jwt.rb:49:in `verify_rsa': undefined method `verify' for #<String:0x007feee39cf3e0> (NoMethodError)
 from /Users/hm/.rvm/gems/ruby-2.3.0@blah/gems/jwt-1.5.4/lib/jwt.rb:139:in `verify_signature'

 
from /Users/hm/.rvm/gems/ruby-2.3.0@blah/gems/jwt-1.5.4/lib/jwt.rb:124:in `decode'
 from jwt_token.rb:40:in `<main>'






On Wednesday, August 3, 2016 at 3:34:15 PM UTC-7, Jacob Wenger wrote:
You are correct that the value for rsa_public should be the full public key string ("-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n") corresponding to the JWT's kid from the URL you posted. If that is not working, please post some code showing what you are trying as well as the error message you are receiving. Without those things, we can only guess at what your problem is.

Jacob
On Wed, Aug 3, 2016 at 3:03 PM, Hiren Mistry <hi...@joinloop.com> wrote:
Jacob,

Got it. 

What's tripping me is what to put for rsa_public so ruby-jwt will run verification? 

JWT.decode(token, rsa_public, true, { :algorithm => 'RS256' })

Based on my understanding from the docs, I tried the public keys (and corresponding key) from https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com.

Jacob Wenger

unread,
Aug 5, 2016, 3:33:16 PM8/5/16
to fireba...@googlegroups.com
Hey Hiren,

I've never used Ruby before, but from what I can tell you can't just pass the PEM string as the input. You instead need to actually create an instance of OpenSSL::PKey first. See here and here. I think you want something like this:

public_keys = { ...Hash of the public keys from the googleapis link... }
public_key = OpenSSL::PKey.read(public_keys["correct key value"])

# use public_key in your JWT.decode() call

Again, apologies for my Ruby ignorance. Hopefully this is enough to get you unstuck.

Cheers,
Jacob

On Thu, Aug 4, 2016 at 4:40 PM, Hiren Mistry <hi...@joinloop.com> wrote:
Jacob,

Thank you for your patience in helping me understand the pieces correctly.

Here's what I'm trying out... very simple. 

The error is in the JWT library where it tries to pass a method `verify` to the string I passed as `rsa_public`. I looked through the JWT doc's but there's not mention `rsa_public` should be of some type so I assume its a string based on example.

If I set verification to false, JWT.decode will decode the token and I can see the contents. But I need verification to work so I know its legit.

Hiren.

require 'jwt' # uses version 1.5.4

public_keys
= { ...Hash of the public keys from the googleapis link... }


token
= "....  JWT token ...."
puts JWT
.decode(token, public_keys["correct key value"], true, { algorithm: "RS256", verify_iat: true }) # you can try other verification options, it doesn't matter



Error I get is:
/Users/hm/.rvm/gems/ruby-2.3.0@blah/gems/jwt-1.5.4/lib/jwt.rb:49:in `verify_rsa': undefined method `verify' for #<String:0x007feee39cf3e0> (NoMethodError)
 from /Users/hm/.rvm/gems/ruby-2.3.0@blah/gems/jwt-1.5.4/lib/jwt.rb:139:in `verify_signature'

 
from /Users/hm/.rvm/gems/ruby-2.3.0@blah/gems/jwt-1.5.4/lib/jwt.rb:124:in `decode'
 from jwt_token.rb:40:in `<main>'






On Wednesday, August 3, 2016 at 3:34:15 PM UTC-7, Jacob Wenger wrote:
You are correct that the value for rsa_public should be the full public key string ("-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n") corresponding to the JWT's kid from the URL you posted. If that is not working, please post some code showing what you are trying as well as the error message you are receiving. Without those things, we can only guess at what your problem is.

Jacob
On Wed, Aug 3, 2016 at 3:03 PM, Hiren Mistry <hi...@joinloop.com> wrote:
Jacob,

Got it. 

What's tripping me is what to put for rsa_public so ruby-jwt will run verification? 

JWT.decode(token, rsa_public, true, { :algorithm => 'RS256' })

Based on my understanding from the docs, I tried the public keys (and corresponding key) from https://www.googleapis.com/robot/v1/metadata/x509/secureto...@system.gserviceaccount.com.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-talk+unsubscribe@googlegroups.com.

To post to this group, send email to fireba...@googlegroups.com.

Hiren Mistry

unread,
Aug 5, 2016, 8:40:31 PM8/5/16
to Firebase Google Group
Hi Jacob,

Thanks for the tips on resolving the ruby-jwt problem. Your idea is another step closer but didn't work because OpenSSL::PKey.read() needs a start line argument in the string which I can do by substituting CERTIFICATE with PUBLIC KEY in the "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" lines. And the saga continues with yet another error "ArgumentError: Could not parse PKey: ASN1 lib"...

At this point, I'll take this with the ruby-jwt or stack overflow since it's a ruby gem issue and not Firebase support issue. I'll post a final solution when I have one incase others have the same issue.

Thanks for all your help,
Hiren.




On Friday, August 5, 2016 at 12:33:16 PM UTC-7, Jacob Wenger wrote:
Hey Hiren,

Based on my understanding from the docs, I tried the public keys (and corresponding key) from https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com.

Hiren Mistry

unread,
Aug 8, 2016, 8:42:40 PM8/8/16
to Firebase Google Group
Hi Jacob,

Here is the final solution. Posting for others who get stuck.
The GoogleAPI links are x509 certificates and not RSA public keys. Trick was we needed to extract the RSA public key from the certificate.

certificates = { ...Hash of the public certificates from the googleapis link... }
x509
= OpenSSL::X509::Certificate.new(certificates["correct key value"])

JWT
.decode(token, x509.public_key, true, { algorithm: "RS256", verify_iat: true }) # call whatever verification you wish to check for



Regards,
Hiren.

Jacob Wenger

unread,
Aug 8, 2016, 8:57:49 PM8/8/16
to fireba...@googlegroups.com
Thanks a lot for following up Hiren! This will be very useful to people in the future.

Based on my understanding from the docs, I tried the public keys (and corresponding key) from https://www.googleapis.com/robot/v1/metadata/x509/secureto...@system.gserviceaccount.com.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-talk+unsubscribe@googlegroups.com.

To post to this group, send email to fireba...@googlegroups.com.

Rodrigo Serradura

unread,
Apr 26, 2017, 6:54:35 PM4/26/17
to Firebase Google Group
Hello, everyone. This thread was very useful for me create my implementation.

Follow in a gist my solution https://gist.github.com/serradura/40a4f05f424262a94f44997681f02d26.

Andrea Chen

unread,
Mar 10, 2018, 10:47:29 AM3/10/18
to Firebase Google Group
Not sure that any of you will ever see this message, but wanted to send a big THANK YOU out into the abyss. This was SO helpful for me. It was everything. Thank you, thank you.
Reply all
Reply to author
Forward
0 new messages