class SSO::Client::Authentications::Passport
Logic to authenticate a Passport
provided by an outsider app to an insider app.
Attributes
passport_id[R]
request[R]
Public Class Methods
new(request)
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 11 def initialize(request) @request = request end
Public Instance Methods
authenticate()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 15 def authenticate debug { 'Performing authentication...' } result = authenticate! if result.success? debug { 'Authentication succeeded.' } return result end debug { "The Client Passport authentication failed: #{result.code}" } Operations.failure :passport_authentication_failed, object: failure_rack_array end
Private Instance Methods
agent()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 204 def agent request.user_agent end
authenticate!()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 32 def authenticate! chip_decryption { |failure| return failure } check_request_signature { |failure| return failure } passport = retrieve_passport { |failure| return failure } passport.verified! Operations.success :passport_received, object: passport end
check_request_signature() { |failure :invalid_passport_signature| ... }
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 55 def check_request_signature debug { "Verifying request signature using Passport secret #{chip_passport_secret.inspect}" } signature_request.authenticate do |passport_id| Signature::Token.new passport_id, chip_passport_secret end debug { 'Signature looks legit.' } Operations.success :passport_signature_valid rescue ::Signature::AuthenticationError => exception debug { "The Signature Authentication failed. #{exception.message}" } yield Operations.failure :invalid_passport_signature end
chip()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 191 def chip params['passport_chip'] end
chip_belongs_to_passport?()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 143 def chip_belongs_to_passport? unless passport_id debug { 'Unknown passport_id' } return false end unless chip_passport_id debug { 'Unknown passport_id' } return false end if passport_id.to_s == chip_passport_id debug { "The chip on passport #{passport_id.inspect} appears to belong to it." } true else info { "The passport with ID #{passport_id.inspect} has a chip with the wrong ID #{chip_passport_id.inspect}" } false end end
chip_ciphertext()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 171 def chip_ciphertext Base64.decode64 encoded_chip_ciphertext end
chip_ciphertext_and_iv()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 187 def chip_ciphertext_and_iv chip.to_s.split '|' end
chip_decryption() { |failure(:missing_chip, object: params)| ... }
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 107 def chip_decryption debug { "Validating chip decryptability of raw chip #{chip.inspect}" } yield Operations.failure(:missing_chip, object: params) if chip.blank? yield Operations.failure(:missing_chip_key) unless chip_key yield Operations.failure(:missing_chip_iv) unless chip_iv yield Operations.failure(:chip_does_not_belong_to_passport) unless chip_belongs_to_passport? Operations.success :here_is_your_chip_plaintext, object: decrypt_chip rescue OpenSSL::Cipher::CipherError => exception yield Operations.failure :chip_decryption_failed, object: exception.message end
chip_digest()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 195 def chip_digest ::OpenSSL::Cipher::AES256.new :CBC end
chip_iv()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 179 def chip_iv Base64.decode64 chip_ciphertext_and_iv.last end
chip_key()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 163 def chip_key ::SSO.config.passport_chip_key end
chip_passport_id()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 139 def chip_passport_id decrypt_chip.to_s.split('|').first end
chip_passport_secret()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 135 def chip_passport_secret decrypt_chip.to_s.split('|').last end
decrypt_chip()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 119 def decrypt_chip @decrypt_chip ||= decrypt_chip! end
decrypt_chip!()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 123 def decrypt_chip! benchmark(name: 'Passport chip decryption') do decipher = chip_digest decipher.decrypt decipher.key = chip_key decipher.iv = chip_iv plaintext = decipher.update(chip_ciphertext) + decipher.final logger.debug { "Decrypted chip plaintext #{plaintext.inspect} using key #{chip_key.inspect} and iv #{chip_iv.inspect} and ciphertext #{chip_ciphertext.inspect}" } plaintext end end
device_id()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 208 def device_id request.params['device_id'] end
encoded_chip_ciphertext()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 175 def encoded_chip_ciphertext chip_ciphertext_and_iv.first end
encoded_chip_iv()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 183 def encoded_chip_iv chip_iv end
failure_rack_array()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 87 def failure_rack_array payload = { success: false, code: :passport_verification_failed } [200, { 'Content-Type' => 'application/json' }, [payload.to_json]] end
ip()
click to toggle source
TODO: Use ActionDispatch::Request#remote_ip
# File lib/sso/client/authentications/passport.rb, line 200 def ip request.ip end
retrieve_passport() { |verification| ... }
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 41 def retrieve_passport debug { 'Retrieving Passport from server...' } if verification.success? && verification.code == :passport_valid_and_modified passport = verification.object passport.modified! debug { "Successfully retrieved Passport with ID #{passport_id} from server." } return passport else debug { 'Could not obtain Passport from server.' } yield verification end end
signature_request()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 92 def signature_request debug { "Verifying signature of #{request.request_method.inspect} #{request.path.inspect} #{request.params.inspect}" } ::Signature::Request.new request.request_method, request.path, request.params end
user_state_digest()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 167 def user_state_digest ::OpenSSL::Digest.new 'sha1' end
verification()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 83 def verification @verification ||= verifier.call end
verifier()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 68 def verifier ::SSO::Client::PassportVerifier.new verifier_options end
verifier_options()
click to toggle source
# File lib/sso/client/authentications/passport.rb, line 72 def verifier_options { passport_id: passport_id, passport_state: 'refresh', passport_secret: chip_passport_secret, user_ip: ip, user_agent: agent, device_id: device_id, } end