我尝试使用用于应用程序身份验证的证书凭证从 Microsoft Azure Active Directory 获取 JWT 令牌。
我对“x5t”的值感到惊讶。
我已经尝试过
但是当我将请求发送到 MSA 登录端点时,我不断收到以下错误
{
"error": "invalid_client",
"error_description": "AADSTS70002: Error validating credentials. AADSTS50012: Client assertion contains an invalid signature. [Reason - The key was not found., Thumbprint of key used by client: '6F67F76B96F6FBBDF9D3EE1DDF7F9A7B877EE9C75DEDBD3DE9C7FB', Configured keys: [Key0:Start=06/01/2018, End=12/31/2099, Thumbprint=6WGktXA64QmA9TPv;Key1:Start=06/01/2018, End=12/31/2099, Thumbprint=rD9Q10sR6Q6ZkDVw;]]\r\nTrace ID: d9e3e276-e878-4b8a-b08b-10c82a0b0600\r\nCorrelation ID: 48ec889d-2376-45a6-9bf0-01b22b0e0c17\r\nTimestamp: 2018-06-01 09:38:24Z",
"error_codes": [
70002,
50012
],
"timestamp": "2018-06-01 09:38:24Z",
"trace_id": "d9e3e276-e878-4b8a-b08b-10c82a0b0600",
"correlation_id": "48ec889d-2376-45a6-9bf0-01b22b0e0c17"
}
如何获取“x5t”的值?
我发现这个site和这个one对于解决x5t问题非常有价值。最简单的方法是手动获取指纹:
echo $(openssl x509 -in your.cert.pem -fingerprint -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64
上述命令中的值是您在 JWT 的 x5t 字段中输入的值。在此之前,我从 azure 收到无效指纹错误。
如果您使用 Ruby,您可以按照此 answer 获取:
p12 = OpenSSL::PKCS12.new(File.read(CERT_FILE), '')
x509_sha1_thumbprint = Base64.encode64(OpenSSL::Digest::SHA1.new(p12.certificate.to_der).digest).strip
jwt_token = JWT.encode payload, p12.key, 'RS256', { typ: 'JWT', x5t: x509_sha1_thumbprint }
x5t
应该是 X509 证书的 SHA-1 指纹,base64url 编码:
4.1.7。 “x5t”(X.509 证书 SHA-1 指纹)标头参数
“x5t”(X.509 证书 SHA-1 指纹)标头参数是 DER 的 base64url 编码的 SHA-1 指纹(也称为摘要) 与密钥对应的 X.509 证书 [RFC5280] 的编码 用于对 JWS 进行数字签名。请注意,证书指纹 有时也称为证书指纹。使用这个 标头参数是可选的。
来源:RFC7515 — https://www.rfc-editor.org/rfc/rfc7515#section-4.1.7
在 Powershell 7.x 中,情况如下。重要提示:不要使用证书中的指纹来计算 x5t,而是像下面那样这样做,
$CertThumbPrint = '<Thumbprint of your cert with private key, stored in machine/Personal'
$CertificatePath = "cert:\localmachine\my\$CertThumbPrint" #<Add the Certificate Path Including Thumbprint here e.g. cert:\currentuser\my\6C1EE1A11F57F2495B57A567211220E0ADD72DC1 >#
$Cert = Get-Item -Path $CertificatePath
# *** use this (and comment the above line) if you want to load the cert from a pfx file instead of getting it from the machine cert store
#$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2((join-path -path $PSScriptRoot -ChildPath "ExtractContractsFrom-ITSystemMBX.pfx"),"<PFX password>")
$CertificateBase64Hash = [System.Convert]::ToBase64String($cert.GetCertHash())
# Use the CertificateBase64Hash and replace/strip to match web encoding of base64
$x5t = $CertificateBase64Hash -replace '\+','-' -replace '/','_' -replace '='
默认指纹输出是SHA256而不是SHA1。
echo $(openssl x509 -in your.cert.pem -fingerprint -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64
因此,我更新了专门在 SHA1 中输出指纹的命令,如下所示,并且它有效。同样的命令也适用于 .crt 证书文件格式:
echo $(openssl x509 -in your.cert.pem -fingerprint -sha1 -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64
获取 Microsoft Azure 指纹的另一种方法是利用上传证书后生成的指纹。使用指纹列值来生成它。
echo "THUMBRINT COLUMN VALUE" |xxd -r -p| openssl enc -a
或
echo "THUMBRINT COLUMN VALUE" |xxd -r -p| base64
import base64
import binascii
hash_hex = "CERT_THUMBPRINT"
hash_bytes = binascii.unhexlify(hash_hex)
hash_base64url = base64.urlsafe_b64encode(hash_bytes).rstrip(b'=').decode('utf-8')
print(hash_base64url)