class FirebaseIdToken::Signature
Deals with verifying if a given Firebase ID Token is signed by one of the Google's x509 certificates that Firebase uses.
Also checks if the resulting JWT payload hash matches with: + `exp` Expiration time + `iat` Issued at time + User's Firebase Project ID + Non-empty UID
## Verifying a Firebase ID Token
*Be sure to configure the gem to set your Firebase Project ID and a Redis server before move any forward.*
**See the README for a complete guide.**
WARNING: Trying to verify a token without any certificate saved in Redis certificates database raises a {Exceptions::NoCertificatesError}.
@example
FirebaseIdToken::Signature.verify(thrusty_token) => {"iss"=>"https://securetoken.google.com/your-project-id", [...]} FirebaseIdToken::Signature.verify(fake_token) => nil
@see Signature#verify
Constants
- JWT_DEFAULTS
Pre-default JWT algorithm parameters as recommended [here](goo.gl/uOK5Jx).
Attributes
Public Class Methods
Loads attributes: `:project_ids` from {FirebaseIdToken::Configuration}, and `:kid`, `:jwt_token` from the related `jwt_token`. @param [String] jwt_token Firebase ID Token
# File lib/firebase_id_token/signature.rb, line 71 def initialize(jwt_token, raise_error: false) @raise_error = raise_error @project_ids = FirebaseIdToken.configuration.project_ids @kid = extract_kid(jwt_token) @jwt_token = jwt_token @firebase_id_token_certificates = FirebaseIdToken.configuration.certificates end
Returns the decoded JWT hash payload of the Firebase ID Token if the signature in the token matches with one of the certificates downloaded by {FirebaseIdToken::Certificates.request}, returns `nil` otherwise.
It will also return `nil` when it fails in checking if all the required JWT fields are valid, as recommended [here](goo.gl/yOrZZX) by Firebase official documentation.
Note that it will raise a {Exceptions::NoCertificatesError} if the Redis certificates database is empty. Ensure to call {Certificates.request} before, ideally in a background job if you are using Rails.
If you would like this to raise and error, rather than silently failing, you can with the `raise_error` parameter. Example:
FirebaseIdToken::Signature .verify(token, raise_error: Rails.env.development?)
@param raise_error [Boolean] default: false @return [nil, Hash]
# File lib/firebase_id_token/signature.rb, line 54 def self.verify(jwt_token, raise_error: false) new(jwt_token, raise_error: raise_error).verify end
Equivalent to `.verify(jwt_token, raise_error: true)`.
@see {Signature.verify} @return [Hash]
# File lib/firebase_id_token/signature.rb, line 62 def self.verify!(jwt_token) new(jwt_token, raise_error: true).verify end
Public Instance Methods
@see Signature.verify
# File lib/firebase_id_token/signature.rb, line 80 def verify certificate = firebase_id_token_certificates.find(@kid, raise_error: @raise_error) return unless certificate payload = decode_jwt_payload(@jwt_token, certificate.public_key) authorize payload end
Private Instance Methods
# File lib/firebase_id_token/signature.rb, line 98 def decode_jwt_payload(token, cert_key) JWT.decode(token, cert_key, true, JWT_DEFAULTS).first rescue StandardError return nil unless @raise_error raise end
# File lib/firebase_id_token/signature.rb, line 90 def extract_kid(jwt_token) JWT.decode(jwt_token, nil, false).last['kid'] rescue StandardError return 'none' unless @raise_error raise end
# File lib/firebase_id_token/signature.rb, line 119 def still_valid?(payload) payload['exp'].to_i > Time.now.to_i && payload['iat'].to_i <= Time.now.to_i end