从Azure活动目录验证JWT


Verifying JWT from Azure Active Directory

我已经按照这里的说明获得了一个web API的访问令牌。

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

我有这个工作,但文档是模糊的,当它涉及到如何验证令牌在PHP。

您可以使用响应中返回的访问令牌对受保护的资源(如web API)进行身份验证。通常,令牌在HTTP请求中使用承载方案呈现给web API,该方案在RFC 6750中有描述。本规范解释了如何在HTTP请求中使用承载令牌来访问受保护的资源。

当web API接收并验证令牌时,它将使本机客户端应用程序访问web API。

如何验证应用程序中的JWT ?我有一个PHP框架,它使用PHP openssl_verify()函数与令牌,签名,密钥和算法,但当我使用Azure的私钥与SHA256算法时,我收到错误:

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

这让我相信我在PHP中使用的键验证是不正确的。目前,我使用的是为Active Directory应用程序生成的私钥,它恰好也是我为"client_secret"使用的值。参数(任何其他值都不会生成令牌,所以这可能是正确的)。

键类似于(BUT IT NOT ACTUALLY):

cLDQWERTYUI12asdqwezxctlkjpoiAn7yhjeutl8jsP=

我认为openssl需要有一个证书…如果是这样,我似乎找不到这个证书在Azure门户中的位置。

我在这里错过了什么?我应该使用openssl_verify()来验证JWT的密钥是什么?我在Azure中的哪里可以找到它?

感谢

,

更新:

我在这里找到了公钥:https://login.windows.net/common/discovery/keys

但是我仍然无法使用提供的X5C来验证签名。如何在PHP中做到这一点?

,

更新2:

我使用a转换为使用'e'和'n'参数的公钥创建一个.pem文件。这收到一个公钥。

现在我得到打开SSL错误解密时使用它:

error:0906D06C:PEM routines:PEM_read_bio:no start line

结束这个问题,因为我已经从最初的问题转移到了下一个问题。更新了我的问题和评论,显示我是如何进步的。

为新的特定问题创建了一个新问题:如何使用公共RSA密钥验证JSON Web令牌?

,

只是为了帮助别人:

关于在PHP中从Microsoft获取公钥的解决方案的进一步信息,我做了以下操作:

$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'];
}

最好把这些缓存到磁盘上,这样你就不用每次都加载了,这只是一个简单的例子。

然后,使用公钥数组,检查JWT报头中的'kid'值,以找到要验证的正确的公共证书,并在openssl_verify()中的参数3中使用它。我使用JWT类来为我处理这个问题。

使用上面创建的公钥数组和JWT类应该允许您验证microsoft JWT。

从firebase链接到JWT类:https://github.com/firebase/php-jwt

调用JWT::解码,使用JWT的参数1,此公钥数组的参数2和仅'RS256'数组的参数3。

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

如果JWT无效或返回一个解密的JWT供您使用(并检查声明),这将抛出一个异常。

如果您想验证jwt,请转到jwt.io这将允许您粘贴JWT,然后它将验证标头、声明,如果您添加公钥或私钥(取决于服务器验证签名的方式),它还将验证JWT的签名。