Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verifying JWT from Azure Active Directory

I have followed the instructions here to obtain an access token for a web API.

https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx

I have this working but the documentation is vague when it comes to figuring out how to validate the token in PHP.

You can use the access token that is returned in the response to authenticate to a protected resources, such as a web API. Typically, the token is presented to the web API in an HTTP request using the Bearer scheme, which is described in RFC 6750. This specification explains how to use bearer tokens in HTTP requests to access protected resources.

When the web API receives and validates the token, it gives the native client application access to the web API.

How do I validate the JWT in application? I have a PHP framework which is using PHP openssl_verify() function with the token, signiture, key and algorithm but I receive error of when I use the private key from Azure with the SHA256 algorithm:

openssl_verify(): supplied key param cannot be coerced into a public key

This leads me to believe that the key I am using in PHP to validate is not correct. At the moment, I am using the private key I generated for the Active Directory Application, which happens to also be the same value I am using for the "client_secret" parameter when hitting the oauth2/token url (any other value causes no token to be generated so this is probably correct).

The key is similar to (BUT IT NOT ACTUALLY):

cLDQWERTYUI12asdqwezxctlkjpoiAn7yhjeutl8jsP=

Where I beleive openssl needs to have a certificate... if so I can't seem to find where this certificate is in the Azure portal.

What am I missing here? What is the key I should be using with openssl_verify() to verify the JWT and where do I find it in Azure?

Thanks

--

UPDATE:

I have found the public keys here: https://login.windows.net/common/discovery/keys

However I still cannot use the X5C provided to verify the signature. How do you do this in PHP?

--

UPDATE 2:

I used a converted to create a .pem file for the public key using both the 'e' and 'n' parameters. This received a public key.

Now I get OPEN SSL errors when decrypting with it:

error:0906D06C:PEM routines:PEM_read_bio:no start line
like image 628
Knightsbridge Avatar asked Aug 21 '15 15:08

Knightsbridge


2 Answers

Closing this question as I have moved on from the origional issue. Updated my question with comments showing how I have progressed.

Created a new question for the new specific issue: How do I verify a JSON Web Token using a Public RSA key?

--

Just in case it helps anyone else:

For further information on a solution to obtaining a public key from Microsoft in PHP I did the following:

$string_microsoftPublicKeyURL = 'https://login.windows.net/common/discovery/keys';

$array_publicKeysWithKIDasArrayKey = loadKeysFromAzure($string_microsoftPublicKeyURL);


function loadKeysFromAzure($string_microsoftPublicKeyURL) {
    $array_keys = array();

    $jsonString_microsoftPublicKeys = file_get_contents($string_microsoftPublicKeyURL);
    $array_microsoftPublicKeys = json_decode($jsonString_microsoftPublicKeys, true);

    foreach($array_microsoftPublicKeys['keys'] as $array_publicKey) {
        $string_certText = "-----BEGIN CERTIFICATE-----\r\n".chunk_split($array_publicKey['x5c'][0],64)."-----END CERTIFICATE-----\r\n";
        $array_keys[$array_publicKey['kid']] = getPublicKeyFromX5C($string_certText);
    }

    return $array_keys;
}


function getPublicKeyFromX5C($string_certText) {
    $object_cert = openssl_x509_read($string_certText);
    $object_pubkey = openssl_pkey_get_public($object_cert);
    $array_publicKey = openssl_pkey_get_details($object_pubkey);
    return $array_publicKey['key'];
}

Its better however to cache these to disk so your not loading these them every time, but this is just a simple example of how to do this.

Then, using the array of public keys, check the JWT header for the 'kid' value to find the correct public cert to verify against and use this in parameter 3 within openssl_verify(). I used the JWT class to deal with this for me.

Using this public key array created above and the JWT class should allow you to validate microsoft JWTs.

Link to JWT class from firebase: https://github.com/firebase/php-jwt

Call JWT::Decode with param 1 of your JWT, param 2 of this public key array and param three of an array of just 'RS256'.

JWT::decode($string_JSONWebToken, $array_publicKeysWithKIDasArrayKey, array('RS256'));

This will throw an exception if the JWT is invalid or return a decrypted JWT for you to use (and check the claims).

like image 84
Knightsbridge Avatar answered Sep 20 '22 20:09

Knightsbridge


If you want to verify the jwt then go to jwt.io This will allow you to paste the JWT and it will then verify the header, claims, and if you add the Public key or private key (depending how the server verifies the signature) it will also verify the signature of the JWT.

like image 45
Paul Pogonoski Avatar answered Sep 21 '22 20:09

Paul Pogonoski