Class: Google::Auth::TokenValidator
- Inherits:
-
Object
- Object
- Google::Auth::TokenValidator
- Defined in:
- lib/googleauth/token_validator.rb,
lib/googleauth/token_validator/version.rb
Defined Under Namespace
Classes: Error
Constant Summary collapse
- GOOGLE_SIGNON_CERTS_URL =
"https://www.googleapis.com/oauth2/v1/certs".freeze
- ISSUERS =
%w(accounts.google.com https://accounts.google.com).freeze
- CLOCK_SKEW_SECONDS =
five minutes
300
- MAX_TOKEN_LIFETIME_SECONDS =
one day
86400
- VERSION =
"0.1.2"
Class Attribute Summary collapse
-
._cached_certs ⇒ Object
Returns the value of attribute _cached_certs.
Instance Attribute Summary collapse
-
#client_id ⇒ Object
readonly
Returns the value of attribute client_id.
-
#envelope ⇒ Object
readonly
Returns the value of attribute envelope.
-
#payload ⇒ Object
readonly
Returns the value of attribute payload.
-
#signature ⇒ Object
readonly
Returns the value of attribute signature.
-
#signed ⇒ Object
readonly
Returns the value of attribute signed.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(jwt, client_id) ⇒ TokenValidator
constructor
A new instance of TokenValidator.
- #validate(max_expiry = MAX_TOKEN_LIFETIME_SECONDS) ⇒ Object
Constructor Details
#initialize(jwt, client_id) ⇒ TokenValidator
Returns a new instance of TokenValidator.
16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/googleauth/token_validator.rb', line 16 def initialize jwt, client_id segments = jwt.split(".") fail Error, "Wrong number of segments in token: #{jwt}" unless segments.size.eql? 3 @client_id = client_id @signed = "#{segments[0]}.#{segments[1]}" @signature = segments[2] @envelope = JSON.parse Base64.decode64(segments[0]) @payload = JSON.parse Base64.decode64(segments[1]) end |
Class Attribute Details
._cached_certs ⇒ Object
Returns the value of attribute _cached_certs.
78 79 80 |
# File 'lib/googleauth/token_validator.rb', line 78 def _cached_certs @_cached_certs end |
Instance Attribute Details
#client_id ⇒ Object (readonly)
Returns the value of attribute client_id.
14 15 16 |
# File 'lib/googleauth/token_validator.rb', line 14 def client_id @client_id end |
#envelope ⇒ Object (readonly)
Returns the value of attribute envelope.
14 15 16 |
# File 'lib/googleauth/token_validator.rb', line 14 def envelope @envelope end |
#payload ⇒ Object (readonly)
Returns the value of attribute payload.
14 15 16 |
# File 'lib/googleauth/token_validator.rb', line 14 def payload @payload end |
#signature ⇒ Object (readonly)
Returns the value of attribute signature.
14 15 16 |
# File 'lib/googleauth/token_validator.rb', line 14 def signature @signature end |
#signed ⇒ Object (readonly)
Returns the value of attribute signed.
14 15 16 |
# File 'lib/googleauth/token_validator.rb', line 14 def signed @signed end |
Class Method Details
._certs ⇒ Object
80 81 82 83 84 85 |
# File 'lib/googleauth/token_validator.rb', line 80 def _certs @_cached_certs ||= begin uri = URI(GOOGLE_SIGNON_CERTS_URL) JSON.parse Net::HTTP.get(uri) end end |
Instance Method Details
#validate(max_expiry = MAX_TOKEN_LIFETIME_SECONDS) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/googleauth/token_validator.rb', line 30 def validate max_expiry = MAX_TOKEN_LIFETIME_SECONDS unless [@signed, @signature, @envelope, @payload].all? fail Error, "Validator was not properly initialized" end unless self.class._certs.keys.include? @envelope["kid"] fail Error, "No matching Google cert found for envelope: #{@envelope}" end pem = self.class._certs[envelope["kid"]] cert = OpenSSL::X509::Certificate.new pem digest = OpenSSL::Digest::SHA256.new verified = cert.public_key.verify(digest, Base64.urlsafe_decode64(@signature), @signed) fail Error, "Token signature invalid" unless verified fail Error, "No issue time in token" if @payload["iat"].to_s.empty? fail Error, "No expiration time in token" if @payload["exp"].to_s.empty? now = Time.now.to_i earliest = @payload["iat"] - CLOCK_SKEW_SECONDS latest = @payload["exp"] + CLOCK_SKEW_SECONDS fail Error, "Expiration time too far in future" if @payload["exp"] >= Time.now.to_i + max_expiry fail Error, "Token used too early" if now < earliest fail Error, "Token used too late" if now > latest unless ISSUERS.include? @payload["iss"] fail Error, "Invalid issuer. Expected one of #{ISSUERS}, but got #{@payload["iss"]}" end if @client_id.is_a? Array aud_verified = @client_id.include?(@payload["aud"]) elsif @client_id.is_a? String aud_verified = @payload["aud"] == @client_id else fail Error, "Invalid client id(s)" end unless aud_verified fail Error, "Wrong recipient - payload audience doesn't match required audience" end return true end |