Class: Eld::Authenticator

Inherits:
Object
  • Object
show all
Defined in:
lib/eld/authenticator.rb

Constant Summary collapse

GOOGLE_ISS =
"https://securetoken.google.com"

Instance Method Summary collapse

Constructor Details

#initialize(firebase_id:) ⇒ Authenticator

Glossary: #

exp Expiration time Must be in the future. The time is measured in seconds since the UNIX epoch. iat Issued-at time Must be in the past. The time is measured in seconds since the UNIX epoch. aud Audience Must be your Firebase project ID, the unique identifier for your Firebase project, which can be found in the URL of that project’s console. iss Issuer Must be “securetoken.google.com/<projectId>”, where <projectId> is the same project ID used for aud above. sub Subject Must be a non-empty string and must be the uid of the user or device. auth_time Authentication time Must be in the past. The time when the user authenticated.



23
24
25
# File 'lib/eld/authenticator.rb', line 23

def initialize(firebase_id:)
  @firebase_id = Array(firebase_id)
end

Instance Method Details

#authenticate(token) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/eld/authenticator.rb', line 27

def authenticate(token)
  return false if token.nil? || token.empty?

  kid = JWT.decode(token, nil, false).last["kid"]

  certificate = Eld::Certificate.find(kid)

  decoded_token = decode_token(token, certificate.public_key)

  valid_token?(decoded_token) && respond(decoded_token)
rescue JWT::DecodeError => e
  handle_error(e)
end

#decode_token(token, public_key) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/eld/authenticator.rb', line 41

def decode_token(token, public_key)
  JWT.decode(
    token,
    public_key,
    true,
    algorithm: "RS256",
    verify_expiration: false # we verify this manually
  ).first
end

#handle_error(_error) ⇒ Object



78
79
80
# File 'lib/eld/authenticator.rb', line 78

def handle_error(_error)
  false
end

#respond(decoded_token) ⇒ Object



74
75
76
# File 'lib/eld/authenticator.rb', line 74

def respond(decoded_token)
  decoded_token
end

#valid_firebase_id?(decoded_token) ⇒ Boolean

Returns:

  • (Boolean)


68
69
70
71
72
# File 'lib/eld/authenticator.rb', line 68

def valid_firebase_id?(decoded_token)
  @firebase_id.any? do |id|
    decoded_token["aud"] == id && decoded_token["iss"] == "#{GOOGLE_ISS}/#{id}"
  end
end

#valid_sub?(decoded_token) ⇒ Boolean

Returns:

  • (Boolean)


62
63
64
65
66
# File 'lib/eld/authenticator.rb', line 62

def valid_sub?(decoded_token)
  !decoded_token["sub"].nil? &&
  !decoded_token["sub"].empty? &&
  decoded_token["sub"] == decoded_token["user_id"]
end

#valid_token?(decoded_token) ⇒ Boolean

Returns:

  • (Boolean)


51
52
53
54
55
56
57
58
59
60
# File 'lib/eld/authenticator.rb', line 51

def valid_token?(decoded_token)
  current_time = Time.now.utc.to_i

  !decoded_token.empty? &&
  decoded_token["exp"].to_i > current_time &&
  decoded_token["iat"].to_i < current_time &&
  decoded_token["auth_time"].to_i < current_time &&
  valid_sub?(decoded_token) &&
  valid_firebase_id?(decoded_token)
end