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

时间:2016-06-21 17:01:38

标签: php azure active-directory single-sign-on jwt

我尝试使用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标记拆分为标题,正文和签名。

然后我可以base64decode标题:

["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]

我设置了谷歌搜索引擎优化,与此相比,这是一件轻而易举的事 - 我确定我错过了一些东西,但它确实看起来过于复杂!

非常感谢任何帮助 - 我已经阅读了很长时间的文档!如果可能的话,我真的很想避免使用库,所以我可以完全理解发生了什么。

1 个答案:

答案 0 :(得分:0)

据我所知,我想我需要用它来解密签名-是吗?

实际上,您需要做的是亲自验证签名。

alg属性告诉您该算法为RS256,即RSA256。我不是Python专家,但快速搜索后便指向我here(不确定该库是否为最好...),您可以在其中验证签名。消息是JWT的前两个块(由“。”分隔),签名是第三个块。