Class: Intuit::Saml
- Inherits:
-
Object
- Object
- Intuit::Saml
- Defined in:
- lib/intuit-saml.rb
Overview
Constant Summary collapse
- @@namespaces =
{ 'ds' => 'http://www.w3.org/2000/09/xmldsig#', 'saml' => 'urn:oasis:names:tc:SAML:2.0:assertion', 'samlp' => 'urn:oasis:names:tc:SAML:2.0:protocol', 'xenc' => 'http://www.w3.org/2001/04/xmlenc#', }
Instance Method Summary collapse
-
#application_destination_url ⇒ Object
extracts the targetUrl from the SAML document - this is referred to as “Application Destination URL” in the Federation Advanced Settings for your app.
-
#debug_info ⇒ Object
returns a hash full of intermediate data for debugging purposes.
-
#initialize(params) ⇒ Saml
constructor
sets up the tool with the SAML XML and the private key corresponding to the public key registered with IPP.
-
#ticket ⇒ Object
extracts the IPP API ticket from the SAML document.
Constructor Details
#initialize(params) ⇒ Saml
48 49 50 51 |
# File 'lib/intuit-saml.rb', line 48 def initialize params @saml_doc = LibXML::XML::Parser.string( params[:saml_xml] ).parse @private_key = OpenSSL::PKey::RSA.new( params[:private_key] ) end |
Instance Method Details
#application_destination_url ⇒ Object
extracts the targetUrl from the SAML document - this is referred to as “Application Destination URL” in the Federation Advanced Settings for your app
98 99 100 101 102 103 |
# File 'lib/intuit-saml.rb', line 98 def application_destination_url @application_destination_url = expected_saml_node_content( @saml_doc, '/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name = "targetUrl"]/saml:AttributeValue' ) rescue Intuit::MissingExpectedSamlNode raise NoDestinationURL.new return @application_destination_url end |
#debug_info ⇒ Object
returns a hash full of intermediate data for debugging purposes
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/intuit-saml.rb', line 106 def debug_info return { :saml_doc => @saml_doc, :encrypted_key => @encrypted_key, :encrypted_ticket => @encrypted_ticket, :decrypted_key => @decrypted_key, :decrypted_ticket => @decrypted_ticket, :ticket => @ticket, } end |
#ticket ⇒ Object
extracts the IPP API ticket from the SAML document
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/intuit-saml.rb', line 54 def ticket # collect relevant parts of the saml document begin @encrypted_key = expected_saml_node_content( @saml_doc, '/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:EncryptedAttribute/xenc:EncryptedData/ds:KeyInfo/xenc:EncryptedKey/xenc:CipherData/xenc:CipherValue' ) rescue Intuit::MissingExpectedSamlNode raise NoEncryptedKey.new end begin @encrypted_ticket = expected_saml_node_content( @saml_doc, '/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:EncryptedAttribute/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue' ) rescue Intuit::MissingExpectedSamlNode raise NoEncryptedTicket.new end # make sure the encryption algorithm is something that is recognized (currently only aes-128 is recognized) encryption_method_node = expected_saml_node( @saml_doc, '/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:EncryptedAttribute/xenc:EncryptedData/xenc:EncryptionMethod' ) algorithm = encryption_method_node.attributes.to_h['Algorithm'] unless algorithm.eql?( 'http://www.w3.org/2001/04/xmlenc#aes128-cbc' ) raise Intuit::UnknownSymmetricEncryptionAlgorithmException.new( "unknown symmetric encryption algorithm #{ algorithm }" ) end # decrypt aes-128 key using rsa @decrypted_key = @private_key.private_decrypt( Base64::decode64( @encrypted_key ) ) # decrypt ticket using aes-128 # http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html#aes128-cbc cipher = OpenSSL::Cipher::Cipher.new( 'AES-128-CBC' ) cipher.decrypt cipher.key = @decrypted_key cipher.padding = 0 ciphertext = Base64::decode64( @encrypted_ticket ) # remove the first 16 bytes and use them as the initialization vector cipher.iv = ciphertext[0,cipher.iv_len] ciphertext = ciphertext[cipher.iv_len..-1] @decrypted_ticket = cipher.update( ciphertext ) + cipher.final # number of padding bytes at the end of the cleartext is recorded in the last byte last_byte = @decrypted_ticket[-1].ord @decrypted_ticket = @decrypted_ticket[0..-last_byte-1] # decrypted value is itself an xml document ticket_doc = LibXML::XML::Parser.string( @decrypted_ticket ).parse @ticket = expected_saml_node_content( ticket_doc, '/saml:Attribute[@Name="ticket"]/saml:AttributeValue' ) end |