php - 从 Azure Active Directory 验证 JWT

标签 php azure openssl cryptography jwt

我已按照此处的说明获取 Web API 的访问 token 。

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

我已经完成了这项工作,但在弄清楚如何在 PHP 中验证 token 时,文档很模糊。

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.

如何在应用程序中验证 JWT?我有一个 PHP 框架,它使用 PHP openssl_verify() 函数以及 token 、签名、 key 和算法,但是当我使用来自 Azure 的私钥和 SHA256 算法时,我收到错误:

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

这让我相信我在 PHP 中用于验证的 key 不正确。目前,我正在使用为 Active Directory 应用程序生成的私钥,该私钥也恰好与我在点击 oauth2/token url 时为“client_secret”参数使用的值相同(任何其他值都会导致没有 token 生成,因此这可能是正确的)。

key 类似于(但实际上不是):

cLDQWERTYUI12asdqwezxctlkjpoiAn7yhjeutl8jsP=

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

我在这里缺少什么?我应该使用 openssl_verify() 来验证 JWT 的 key 是什么?在 Azure 中哪里可以找到它?

谢谢

--

更新:

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

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

--

更新2:

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

现在我在使用它解密时遇到 OPEN SSL 错误:

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

最佳答案

结束这个问题,因为我已经离开了原来的问题。用评论更新了我的问题,显示了我的进展。

针对新的具体问题创建了一个新问题:How do I verify a JSON Web Token using a Public RSA key?

--

以防万一对其他人有帮助:

有关在 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 header 中的“kid”值,以找到要验证的正确公共(public)证书,并在 openssl_verify() 内的参数 3 中使用它。我使用 JWT 类来帮我处理这个问题。

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

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

使用 JWT 的参数 1、此公钥数组的参数 2 和“RS256”数组的参数 3 调用 JWT::Decode。

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

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

关于php - 从 Azure Active Directory 验证 JWT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32143743/

相关文章:

php - 为什么mcrypt中会出现这些奇怪的字符?

php - 设置模型响应与关系

java - 虚拟机规模集支持

ssl - 如何在Openssl中实现客户端相互认证?

php - jquery 视口(viewport)大小更改 timthumb 输出

sql-server - Azure SQL 查询速度慢

azure - 是否可以将 Windows 事件日志获取到应用程序洞察中?

encryption - OpenSSL - 密码与盐目的

c++ - Openssl,无效参数 ' Candidates are: int BN_set_word(bignum_st *, ?) '

php - 使用 codeigniter 在数据库中设置一个值,它将把输出返回到同一页面