【发布时间】:2022-02-06 08:45:15
【问题描述】:
我正在尝试使用ms docs 中描述的流程来验证 azure 活动目录 ID 和访问令牌。我正在浏览器中执行此操作。我知道在前端这样做是没有意义的。我还是想知道怎么做。只是出于好奇。
https://jwt.io/ 上有类似的东西。它旨在调试令牌。它可以判断签名是否有效。
在我的代码中,验证总是失败。我不确定在这种情况下我是否正确使用了SubtleCrypto。我也不确定我是否为其功能选择了正确的参数,比如算法。
访问令牌的标头看起来总是这样,使用 RS256。
{
"typ": "JWT",
"nonce": "<redacted>",
"alg": "RS256",
"x5t": "<redacted>",
"kid": "<redacted>"
}
匹配的 JWK 如下所示。
{
"kty": "RSA",
"use": "sig",
"kid": "<redacted>",
"x5t": "<redacted>",
"n": "<redacted>",
"e": "<redacted>",
"x5c": ["<redacted>"]
}
我创建了这个函数来使用声明中的颁发者 URL 和标头中的孩子属性获取 JWK,并最终验证签名。 crypto.subtle.verify 总是返回 false。
async function verifyToken(rawToken) {
// parse the token into parts
const [encodedHeaders, encodedClaims, signature] = rawToken.split(".");
const header = JSON.parse(atob(encodedHeaders));
const claims = JSON.parse(atob(encodedClaims));
// get the openid config using the issuer url
const issuer_url = claims.iss.endsWith("/") ? claims.iss : claims.iss + "/";
const openIdConfiguration = await (
await fetch(`${issuer_url}.well-known/openid-configuration`)
).json();
// get the jwk list
const jwkList = await (
await fetch(openIdConfiguration.jwks_uri)
).json();
// find the jwk for the kid in the token header
const matchedKey = jwkList.keys.find(k => k.kid === header.kid)
// return early if no jwk is found
if (!matchedKey) return {
rawToken,
header,
claims,
signature,
openIdConfiguration,
jwkList,
};
// import the jwk into a a crypto key
const pubkey = await crypto.subtle.importKey(
"jwk",
matchedKey,
{ name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" } },
true,
["verify"],
);
// verify the signature
const verified = await crypto.subtle.verify(
{ name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" } },
pubkey,
new TextEncoder().encode(signature),
new TextEncoder().encode(encodedHeaders + "." + encodedClaims),
);
// return the results
return {
rawToken,
header,
claims,
signature,
openIdConfiguration,
jwkList,
matchedKey,
verified
};
};
【问题讨论】:
标签: javascript azure-active-directory jwt cryptography