OKTA SAML Signature verIfication - PHP Skip to main content
https://support.okta.com/help/answers?id=906f0000000xzdziao&refurl=http%3a%2f%2fsupport.okta.com%2fhelp%2fanswers
How satisfied are you with the Okta Help Center?
Thank you for your feedback!
How satisfied are you with the Okta Help Center?
1
2
3
4
5
Very Dissatisfied
Very satisfied
Enter content less than 200 characters.
Ask Search:
Narayan GowrajNarayan Gowraj 

OKTA SAML Signature verIfication - PHP

My application (PHP) gets the SAML response back from OKTA which has the signature value and I also have OKTA's certificate which has the public key. My application does the following,

1. Gets the public key from the cert.
2. Gets the signature value from the SAML sent to it.
3. Now, it uses the function openssl_verify($data, $signature, $pubkeykey,"sha1WithRSAEncryption"); Since $data is the content used by OKTA to sign the saml response, I am not sure what $data has to set.

My Code,$pubkeyid = openssl_pkey_get_details(openssl_pkey_get_public(file_get_contents("okta.cert"))); $pubkeyid = $pubkeyid["key"]; $signature = "<get it form SAML Response>"; $data = ???? (what should be provided) $ok = openssl_verify($data, $signature, $pubkeyid,"sha1WithRSAEncryption");

Am I missing something ?
Madhu Mahadevan - SEMadhu Mahadevan - SE (Okta, Inc.)
Hi there!

Not sure about the context here. However, are you using any libraries such as https://simplesamlphp.org ?  If not, using simpleSAMLphp or something similar to process SAML transactions would be a better approach.

 
Narayan GowrajNarayan Gowraj
Hi Madhu,

Yes, I am using SimpleSamlPHP and I have the SAML working perfectly. I am trying the verify the signature that I get with the SAML Assertion (sent from OKTA) and I also the public key to decrypt the signature. To verify, I use,

openssl_verify($data, $signature, $pubkeyid,"sha1WithRSAEncryption");

I have the value of signature, pubkeyid but I am not sure what data was used by OKTA to generate the siagnture. I skimmed through a lot of OKTA docs but couldn't find the answer to it. 


 
api-workday api-workdayapi-workday api-workday
Hi Narayan,

I'm not familiar with simpleSamlphp and i could be missing your intent but i'll take a stab.

in Okta's SAML application configuration you have the ability to:
  • Not Sign anything
  • Sign the SAML Response <saml2p:Response> ... </saml2p:Response>
  • Sign the SAML Assertion <saml2:Assertion> ... </saml2:Assertion>
  • Sign both the Response and Assertion (seems duplicitious since the Assertion is fully contained in the response and they are both generated from the same source)
That said if you have SimpleSamlPHP configured and it is accepting the response what additional verification are you trying to perform that SimpleSAML hasn't already performed, my casual interactions with it as an IdP is that it performs sufficient verification on its own.

-Matt
Narayan GowrajNarayan Gowraj
Hello Matt, 

I am trying to verify the signature in the SAML Response which is sent from OKTA. I am doing this explicitly so that I can achieve non-repudiation and integrity. For example, 

1. This is the SAML Response which I get from OKTA. The signature is highlighted in bold. 

<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                 Destination="https://db-patch.rfiserve.net/stg_patch.php"
                 ID="id135518416966088152083982497"
                 InResponseTo="_5a33438be6441498e4f5baaba038e2df393fd6382f"
                 IssueInstant="2015-08-10T18:01:46.364Z"
                 Version="2.0"
                 >
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                  Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
                  >http://www.okta.com/exk13kwqims02XUmL1d8</saml2:Issuer>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <ds:Reference URI="#id135518416966088152083982497">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <ds:DigestValue>6tn05lZjTsHJ+XBhify/+/P0vg0=</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>WRZVWKqmwGbYIdQyURU2pbgp0Ei7J7KIkolgUPbtbCNHmgVRsyLwf40UVlAkGgQ9XFjFoAJEb6hhe7vhVuwJqqG5ukwonBM2IuSNwrb7/ZguSTPqXngA1/hnnvRdoMuTg2dcze6B6ocfOFN2ERW/QMTw+OwpVJxdbaVLy4E4Kxp+SFvwRrammWC6+8mOdGoJY/csT82/gUf2yUsYz081DIiN5O71OvYxZ/jFz707dlxvQQyH8sLGibz74DGkIK9rfv7wjwD7Pa5k+yqVpGEYy8oPdDornik/i/C9dQj3vLe/VQAJo4aE2okkkV8w6c12vAdlssgS7mYJuyGzUeuESA==</ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAUtCTU/cMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU
MBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCnJvY2tldGZ1ZWwxHDAaBgkqhkiG9w0BCQEW
DWluZm9Ab2t0YS5jb20wHhcNMTUwMTMxMjMyMTE3WhcNNDUwMTMxMjMyMjE3WjCBkjELMAkGA1UE
BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNV
BAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApyb2NrZXRmdWVsMRwwGgYJ
KoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
iOcqxQ1F7UwnKAbq4yVnih3hPJGEnS8g7hFEnV7t0xbqWesFXY5mycxRFpyRPgbED8FBdQuNhlF0
g/IiOyMiKy7n6vjHfJSXvF4ro2/P6tDvMDtHliWksJwSSqsHAjVCJSQYMQ7EHYxu+5s0rcQM7hSx
+8YV70nqvmsDIqFMQnzPW4k9FvF4Ny9foaHdq7ldUjvI1B+Ur+asg7dHk0Cle0qv7dDjimPHohvg
8nZCTW1n6nZlKZjKid6REefXgzvi/O+3yJRXajLH/a7I/gtBjvEl8WJG+m0Pt0SguanEjX9D84/F
W9mgubthzh0ipE6EZeZYTVTJa8TTVah0yR3UawIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBtlqPK
YghKKv4sD7J33Y4y3brBrnfuQffxCk8+U5bcoLQ8RNs8JAGCaE2stMHCa8fw5ScOg9WqEvRqe1PM
+qGIWyS0cY2I2JS+au2Mkt+WofysRuWwP3f5Kbv8LsLNluOJ3PAIE2D0qP+tbdNE5Vl6JsQuHbRD
OYl7uxGzBI9SpGTCu80yYGJQOxkINj0TA00ZHdg+CQNGCg/02ROL3kQm0h1xVgGH8bdcujUSWTz6
VMeWaE7fUekL6wo0FKgWO0AfKbdDgTPL2cMGtv3qxu6jQYh4KCcDl4IHi4x2MKWttUym8WegR8JD
mTcy27YsQEPWc71aC1RyMEDS2UG71TD9</ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
    <saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    </saml2p:Status>
    <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                     ID="id135518416967154401922171881"
                     IssueInstant="2015-08-10T18:01:46.364Z"
                     Version="2.0"
                     >
        <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
                      xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                      >http://www.okta.com/exk13kwqims02XUmL1d8</saml2:Issuer>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
                <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
                <ds:Reference URI="#id135518416967154401922171881">
                    <ds:Transforms>
                        <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                    </ds:Transforms>
                    <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                    <ds:DigestValue>j8mFy0xiirGedSet/k8wbezSTGU=</ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>KkeIPbFrLdjDy8xJH+FJ/8a4hNpbL+O4ArdsskEJtPH9xrS38CuVy9lMui4rF5LdgAL1e73SlQMFoA+8eH3KS5U4yAcrBp+mEOQvbE0iw1pDoa1T+kaYHsZh0XOZ4Tni6x2DbQJ7JAUMsnYJ0Obvznny4JAqwKBL8nUciRADrQYqkAJr11viO+x44L9kDrDZeRqFf3kilqHr+BOVeaI/qyfPy1fAzmcQ9pm9lTyuMeFFn07RYJ3EJuNDGnk7eA+1g+E1wbn7LPmaXbGMfud6PM478P3iMc0+eRf9//HfsXtplfCL0Tg7FxR3RgzLzrmnQwipu3tP3jI/f/6QgFfdmA==</ds:SignatureValue>
            <ds:KeyInfo>
                <ds:X509Data>
                    <ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAUtCTU/cMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU
MBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCnJvY2tldGZ1ZWwxHDAaBgkqhkiG9w0BCQEW
DWluZm9Ab2t0YS5jb20wHhcNMTUwMTMxMjMyMTE3WhcNNDUwMTMxMjMyMjE3WjCBkjELMAkGA1UE
BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNV
BAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApyb2NrZXRmdWVsMRwwGgYJ
KoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
iOcqxQ1F7UwnKAbq4yVnih3hPJGEnS8g7hFEnV7t0xbqWesFXY5mycxRFpyRPgbED8FBdQuNhlF0
g/IiOyMiKy7n6vjHfJSXvF4ro2/P6tDvMDtHliWksJwSSqsHAjVCJSQYMQ7EHYxu+5s0rcQM7hSx
+8YV70nqvmsDIqFMQnzPW4k9FvF4Ny9foaHdq7ldUjvI1B+Ur+asg7dHk0Cle0qv7dDjimPHohvg
8nZCTW1n6nZlKZjKid6REefXgzvi/O+3yJRXajLH/a7I/gtBjvEl8WJG+m0Pt0SguanEjX9D84/F
W9mgubthzh0ipE6EZeZYTVTJa8TTVah0yR3UawIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBtlqPK
YghKKv4sD7J33Y4y3brBrnfuQffxCk8+U5bcoLQ8RNs8JAGCaE2stMHCa8fw5ScOg9WqEvRqe1PM
+qGIWyS0cY2I2JS+au2Mkt+WofysRuWwP3f5Kbv8LsLNluOJ3PAIE2D0qP+tbdNE5Vl6JsQuHbRD
OYl7uxGzBI9SpGTCu80yYGJQOxkINj0TA00ZHdg+CQNGCg/02ROL3kQm0h1xVgGH8bdcujUSWTz6
VMeWaE7fUekL6wo0FKgWO0AfKbdDgTPL2cMGtv3qxu6jQYh4KCcDl4IHi4x2MKWttUym8WegR8JD
mTcy27YsQEPWc71aC1RyMEDS2UG71TD9</ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </ds:Signature>
        <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
            <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">ngowraj@rocketfuelinc.com</saml2:NameID>
            <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml2:SubjectConfirmationData InResponseTo="_5a33438be6441498e4f5baaba038e2df393fd6382f"
                                               NotOnOrAfter="2015-08-10T18:06:46.365Z"
                                               Recipient="https://db-patch.rfiserve.net/stg_patch.php"
                                               />
            </saml2:SubjectConfirmation>
        </saml2:Subject>
        <saml2:Conditions NotBefore="2015-08-10T17:56:46.365Z"
                          NotOnOrAfter="2015-08-10T18:06:46.365Z"
                          xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                          >
            <saml2:AudienceRestriction>
                <saml2:Audience>https://db-patch.rfiserve.net/stg_patch.php</saml2:Audience>
            </saml2:AudienceRestriction>
        </saml2:Conditions>
        <saml2:AuthnStatement AuthnInstant="2015-08-10T18:01:46.364Z"
                              SessionIndex="_5a33438be6441498e4f5baaba038e2df393fd6382f"
                              xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                              >
            <saml2:AuthnContext>
                <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
            </saml2:AuthnContext>
        </saml2:AuthnStatement>
    </saml2:Assertion>
</saml2p:Response>

2. I also have the cert from OKTA which has the public key to decrypt this signature and verify that it has come from the trusted IDP. 

3. This is my php code, 
$pubkeyid = openssl_pkey_get_details(openssl_pkey_get_public(file_get_contents("okta.cert")));
	$pubkeyid = $pubkeyid["key"];
	
	// Signature from OKTA SAML Response
	$signature = "WRZVWKqmwGbYIdQyURU2pbgp0Ei7J7KIkolgUPbtbCNHmgVRsyLwf40UVlAkGgQ9XFjFoAJEb6hhe7vhVuwJqqG5ukwonBM2IuSNwrb7/ZguSTPqXngA1/hnnvRdoMuTg2dcze6B6ocfOFN2ERW/QMTw+OwpVJxdbaVLy4E4Kxp+SFvwRrammWC6+8mOdGoJY/csT82/gUf2yUsYz081DIiN5O71OvYxZ/jFz707dlxvQQyH8sLGibz74DGkIK9rfv7wjwD7Pa5k+yqVpGEYy8oPdDornik/i/C9dQj3vLe/VQAJo4aE2okkkV8w6c12vAdlssgS7mYJuyGzUeuESA==";
	
	// Data that was used by OKTA to sign the SAML
	
	$data = 
	
	
	$ok = openssl_verify($data, $signature, $pubkeyid,"sha1WithRSAEncryption");
	if ($ok == 1) {
		echo "good";
	} elseif ($ok == 0) {
		echo "bad";
	} else {
		echo "ugly, error checking signature";
	}
So I am confused what should be the value of $data since $data is what OKTA has signed using its private key.