使用 PHP 从 login.microsoftonline.com 验证 JWT 中的签名

Posted

技术标签:

【中文标题】使用 PHP 从 login.microsoftonline.com 验证 JWT 中的签名【英文标题】:Validate signature in JWT from login.microsoftonline.com with PHP 【发布时间】:2016-10-23 08:34:53 【问题描述】:

我正在尝试使用Azure Active Directory / OpenID Connect services from Microsoft 为网页设置单点登录服务。

我有一些办法,因为我可以让他们的服务向我发送一个 id_token,但我正在努力解决如何验证/验证该令牌。当我从用户浏览器收到它而不是通过服务器到服务器的请求时,我需要验证它,对吗?

为了获取令牌,我只使用了一个链接:

https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=[myclientid]&response_type=id_token&redirect_uri=https://localhost/ssotest.php&response_mode=form_post&scope=openid+profile&state=12345&nonce=678910

(对于那些试图这样做的人,我花了很长时间才找到,但您可以在此处设置您的客户 ID:https://apps.dev.microsoft.com/)

然后该页面将数据发布到我的脚本中,如下所示:

array(3) 
  ["id_token"]=>
  string(1026) "abc.def.geh"
  ["state"]=>
  string(5) "12345"
  ["session_state"]=>
  string(36) "dd7781aa-74e8-4aa8-ac7e-d3800c5c2247"

从那时起,我根据句点/句号将 ID 令牌分为标头、正文和签名。

然后我可以对标头进行base64解码:

["typ"]=> string(3) "JWT"
["alg"]=> string(5) "RS256"
["kid"]=> string(27) "MnC_VZcATfM5pOYiJHMba9goEKY" 

和身体:

["aud"]=> string(36) "[client_id]"
["iss"]=> string(75) "https://login.microsoftonline.com/52f161e7.../v2.0"
["iat"]=> int(1466523280)
["nbf"]=> int(1466523280)
["exp"]=> int(1466527180)
["ipaddr"]=> string(15) "111.111.111.111"
["name"]=> string(12) "Mr E Xample"
["nonce"]=> string(6) "678910"
["oid"]=> string(36) "c3beeb42..."
["preferred_username"]=> string(23) "email@example.co.uk"
["sub"]=> string(43) "oGAnGQ..."
["tid"]=> string(36) "52f161e7..."
["ver"]=> string(3) "2.0"

现在我有一个签名,但我不确定如何处理它。我知道我可以从 https://login.microsoftonline.com/common/discovery/v2.0/keys 获得正确的公共证书,如标题中的 kid 所指定,但我不确定这有什么帮助。由于我知道公钥,我想我需要用它来解密签名 - 对吗??

肯定有办法发送服务器到服务器请求来验证从客户端发送给我的信息吗?例如。 GET https://login.microsoftonline.com/verfifytoken/[token]

我设置了 Google SSO,与此相比,这是轻而易举的事 - 我确定我遗漏了一些东西,但它确实看起来过于复杂!

非常感谢任何帮助 - 我已经阅读文档好几个小时了!如果可能的话,我真的很想避免为此使用库,这样我就可以完全理解正在发生的事情。

【问题讨论】:

根据我的经验,我们可以在你的header中使用[Authorization": id_token]。你可以用这个header请求你的App URL(你使用URL注册App)。 威尔,我想你的意思不是“授权”:id_token,而是授权:承载[id_token]? this might help 【参考方案1】:

我知道公钥,我想我需要用它来解密签名 - 对吗??

其实,你需要做的是自己验证签名。

alg 属性告诉你算法是 RS256,这意味着 RSA 256。我不是 Python 人,但快速搜索指向我 here(不确定这个库是否是最好的...... ) 您可以在其中验证签名。消息是 JWT 的前两个块(由“.”分隔),签名是第三块。

【讨论】:

以上是关于使用 PHP 从 login.microsoftonline.com 验证 JWT 中的签名的主要内容,如果未能解决你的问题,请参考以下文章

php 使用PHP从文件夹显示图像

PHP 使用cURL PHP从URL获取数据

PHP 使用PHP从Array生成CSV文件

使用 PHP 从 localhost 发送邮件

我需要使用 PHP 从 html/php 文件中删除动态信息

PHP 如何使用PHP从Google图像中获取图像