如何在不使用库的情况下验证本机 Javascript 中的 Azure OAuth 访问 JWT 令牌?

Posted

技术标签:

【中文标题】如何在不使用库的情况下验证本机 Javascript 中的 Azure OAuth 访问 JWT 令牌?【英文标题】:How to verify an Azure OAuth Access JWT Token in native Javascript without using a library? 【发布时间】:2020-05-12 23:17:01 【问题描述】:

我有一个 OAuth 访问令牌(来自 Azure)。我想验证签名。

我已经解码了令牌

标题


  "typ": "JWT",
  "alg": "RS256",
  "x5t": "abc123",
  "kid": "abc123"

还有有效载荷


  "aud": "api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "iss": "https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/",
  "iat": 1580132587,
  "nbf": 1580132587,
  "exp": 1580136487,
  "acct": 0,
  "acr": "1",
  "aio": "xxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxx==",
  "amr": [
    "pwd"
  ],
  "appid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxf",
  "appidacr": "0",
  "ipaddr": "yyy.yyy.yyy.yyy",
  "name": "test",
  "oid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "scp": "user_impersonation",
  "sub": "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "tid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "unique_name": "test@mycompany.onmicrosoft.com",
  "upn": "test@mycompany.onmicrosoft.com",
  "uti": "xxxxxxxxxxxxx-xxxxxxxxx",
  "ver": "1.0"

(验证目标受众(aud)后)我需要验证签名。为此,我首先需要计算签名。这样做

    我需要调用 Azure 元数据文档来确认标头中的公钥。

https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/v2.0/.well-known/openid-configuration

    从中我得到了公钥(JWKS URI),例如

https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/discovery/v2.0/keys

    这给了我一个数组

    [
        "kty": "RSA",
        "use": "sig",
        "kid": "abc123",
        "x5t": "abc123",
        "n": "...",
        "e": "...",
        "x5c": [..."],
        "issuer": " https: //login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/v2.0"
        , 
        "kty": "RSA",
        "use": "sig",
        "kid": "...",
        "x5t": "...",
        "n": "....",
        "e": "...",
        "x5c": ["."],
        "issuer": "https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/v2.0"
        ,
    ]
    

    我检查 kidx5t 是否与标题中的字段匹配。

问题

    如何计算实际签名?在我的情况下,签名算法是 RS256,所以我必须做这样的事情

RSASHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), public_key)

    什么是 public_key? 在原生 javascript 中是否有函数 RSASHA256 ?

【问题讨论】:

【参考方案1】:

获取与收到的令牌的孩子匹配的 x5t。那是公钥,尽管它通常需要转换为 PEM 格式。

然后,大多数人使用经过认证的库来验证带有公钥的签名。 Here is some code of mine 这样做是为了验证 Azure 令牌。

我认为原生 JavaScript 是指 NodeJS,因为访问令牌是由 API 而不是 UI 验证的。

最终我相信像 jsonwebtoken 这样的库调用底层操作系统加密代码 - 不适合胆小的人..

【讨论】:

以上是关于如何在不使用库的情况下验证本机 Javascript 中的 Azure OAuth 访问 JWT 令牌?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不丢失身份验证的情况下模拟Session.request?

如何在不使用 3rd-party API 的情况下用 C# 压缩文件?

如何在不使用 Python 中的外部库的情况下解析 arff 文件

如何在不使用支持库的情况下实现水平滑动?

(如何)我可以在不安装完整的 boost 库的情况下使用 boost::spirit X3 吗?

如何在不使用本机代码的情况下要求用户在 NativeScript 上启用蓝牙