IdentityServer4 PKCE error: "Transformed code verifier does not match code challenge"
IdentityServer4 PKCE error: "Transformed code verifier does not match code challenge"
我无法获得使用 Postman 工作的 IdentityServer4 PKCE 授权。
我使用在线工具创建必要的部分:
选择一个随机字符串:
1234567890
获取其 SHA-256 哈希值:
c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
Base64 编码哈希以获得代码挑战:
Yzc3NWU3Yjc1N2VkZTYzMGNkMGFhMTExM2JkMTAyNjYxYWIzODgyOWNhNTJhNjQyMmFiNzgyODYyZjI2ODY0Ng==
在浏览器中,我导航到以下 URL,填写我的凭据并从零散的重定向中检索代码 URL。
GET https://localhost:5000/connect/authorize
?client_id=pkceclient
&scope=openid
&response_type=code
&redirect_uri=https://jwt.ms
&state=abc
&nonce=xyz
&code_challenge=Yzc3NWU3Yjc1N2VkZTYzMGNkMGFhMTExM2JkMTAyNjYxYWIzODgyOWNhNTJhNjQyMmFiNzgyODYyZjI2ODY0Ng==
&code_challenge_method=S256
兑换令牌代码时,我传递了 code_verifier(SHA-256 哈希),但我的 IdentityServer 记录了以下错误:
"Transformed code verifier does not match code challenge".
POST https://localhost:5000/connect/token
client_id=pkceclient
grant_type=authorization_code
code:-CesrmjPYjdLdDd5AviOZpR6GdjjkZia_ZapoJdGUZI
redirect_uri=https://jwt.ms
code_verifier=c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
在他的blog post中,作者使用以下代码生成零件。
var verifier = CryptoRandom.CreateRandomKeyString(64);
var challenge = verifier.ToCodeChallenge();
但我在存储库中找不到 ToCodeChallenge
方法的代码。
为什么我手动生成的挑战与验证过程中使用的挑战不匹配,我错过了什么?
在整理这个问题时,我看到了 PKCE 的 specification 文档并找到了以下行:
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
原来我用的在线工具没有执行ASCII部分
执行代码中的步骤,我得到以下内容,当替换之前的值时,在过程的第二步中通过验证。
var codeVerifier = "c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646";
var codeVerifierBytes = Encoding.ASCII.GetBytes(codeVerifier);
var hashedBytes = codeVerifierBytes.Sha256();
var transformedCodeVerifier = Base64Url.Encode(hashedBytes);
code_challenge: 51FaJvQFsiNdiFWIq2EMWUKeAqD47dqU_cHzJpfHl-Q
code_verifier: c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
以下链接有助于实现 PKCE-AuthZ-Code 流程。
https://auth0.com/docs/api-auth/tutorials/authorization-code-grant-pkce
https://github.com/gilbert-fernandes/S256Code/blob/master/src/S256Code.java
此处对所选答案略作改进,无需 Sha256()
扩展方法 (credit)。
code_verifier
随机生成器(对于 /connect/token
端点):
private string GenerateCodeVerifier()
{
var rng = RandomNumberGenerator.Create();
var bytes = new byte[32];
rng.GetBytes(bytes);
// It is recommended to use a URL-safe string as code_verifier.
// See section 4 of RFC 7636 for more details.
var code_verifier = Convert.ToBase64String(bytes)
.TrimEnd('=')
.Replace('+', '-')
.Replace('/', '_');
return code_verifier;
}
code_challenge
生成器基于 code_verifier
(对于 /connect/authorize
端点):
private string GenerateCodeChallenge(string code_verifier)
{
var code_challenge = string.Empty;
using (var sha256 = SHA256.Create())
{
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(code_verifier));
code_challenge = Convert.ToBase64String(challengeBytes)
.TrimEnd('=')
.Replace('+', '-')
.Replace('/', '_');
return code_challenge;
}
}
用法:
using System;
using System.Security.Cryptography;
using System.Text;
[TestMethod]
public void CodesTest()
{
string code_verifier = GenerateCodeVerifier();
Console.WriteLine("code_verifier:");
Console.WriteLine(code_verifier);
string code_challenge = GenerateCodeChallenge(code_verifier);
Console.WriteLine("code_challenge:");
Console.WriteLine(code_challenge);
}
将输出:
code_verifier:
3t1_Ve6NezEoLtj-7GKAWuXOOEUXe0z9Bd-uKoZeBnE
code_challenge:
cmcJe_eAcSGnEema7PXUEDZZOSofeaUDhKJC5P--uOY
我的 article
中的其他信息
我无法获得使用 Postman 工作的 IdentityServer4 PKCE 授权。
我使用在线工具创建必要的部分:
选择一个随机字符串:
1234567890
获取其 SHA-256 哈希值:
c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
Base64 编码哈希以获得代码挑战:
Yzc3NWU3Yjc1N2VkZTYzMGNkMGFhMTExM2JkMTAyNjYxYWIzODgyOWNhNTJhNjQyMmFiNzgyODYyZjI2ODY0Ng==
在浏览器中,我导航到以下 URL,填写我的凭据并从零散的重定向中检索代码 URL。
GET https://localhost:5000/connect/authorize
?client_id=pkceclient
&scope=openid
&response_type=code
&redirect_uri=https://jwt.ms
&state=abc
&nonce=xyz
&code_challenge=Yzc3NWU3Yjc1N2VkZTYzMGNkMGFhMTExM2JkMTAyNjYxYWIzODgyOWNhNTJhNjQyMmFiNzgyODYyZjI2ODY0Ng==
&code_challenge_method=S256
兑换令牌代码时,我传递了 code_verifier(SHA-256 哈希),但我的 IdentityServer 记录了以下错误:
"Transformed code verifier does not match code challenge".
POST https://localhost:5000/connect/token
client_id=pkceclient
grant_type=authorization_code
code:-CesrmjPYjdLdDd5AviOZpR6GdjjkZia_ZapoJdGUZI
redirect_uri=https://jwt.ms
code_verifier=c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
在他的blog post中,作者使用以下代码生成零件。
var verifier = CryptoRandom.CreateRandomKeyString(64);
var challenge = verifier.ToCodeChallenge();
但我在存储库中找不到 ToCodeChallenge
方法的代码。
为什么我手动生成的挑战与验证过程中使用的挑战不匹配,我错过了什么?
在整理这个问题时,我看到了 PKCE 的 specification 文档并找到了以下行:
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
原来我用的在线工具没有执行ASCII部分
执行代码中的步骤,我得到以下内容,当替换之前的值时,在过程的第二步中通过验证。
var codeVerifier = "c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646";
var codeVerifierBytes = Encoding.ASCII.GetBytes(codeVerifier);
var hashedBytes = codeVerifierBytes.Sha256();
var transformedCodeVerifier = Base64Url.Encode(hashedBytes);
code_challenge: 51FaJvQFsiNdiFWIq2EMWUKeAqD47dqU_cHzJpfHl-Q
code_verifier: c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
以下链接有助于实现 PKCE-AuthZ-Code 流程。
https://auth0.com/docs/api-auth/tutorials/authorization-code-grant-pkce
https://github.com/gilbert-fernandes/S256Code/blob/master/src/S256Code.java
此处对所选答案略作改进,无需 Sha256()
扩展方法 (credit)。
code_verifier
随机生成器(对于 /connect/token
端点):
private string GenerateCodeVerifier()
{
var rng = RandomNumberGenerator.Create();
var bytes = new byte[32];
rng.GetBytes(bytes);
// It is recommended to use a URL-safe string as code_verifier.
// See section 4 of RFC 7636 for more details.
var code_verifier = Convert.ToBase64String(bytes)
.TrimEnd('=')
.Replace('+', '-')
.Replace('/', '_');
return code_verifier;
}
code_challenge
生成器基于 code_verifier
(对于 /connect/authorize
端点):
private string GenerateCodeChallenge(string code_verifier)
{
var code_challenge = string.Empty;
using (var sha256 = SHA256.Create())
{
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(code_verifier));
code_challenge = Convert.ToBase64String(challengeBytes)
.TrimEnd('=')
.Replace('+', '-')
.Replace('/', '_');
return code_challenge;
}
}
用法:
using System;
using System.Security.Cryptography;
using System.Text;
[TestMethod]
public void CodesTest()
{
string code_verifier = GenerateCodeVerifier();
Console.WriteLine("code_verifier:");
Console.WriteLine(code_verifier);
string code_challenge = GenerateCodeChallenge(code_verifier);
Console.WriteLine("code_challenge:");
Console.WriteLine(code_challenge);
}
将输出:
code_verifier:
3t1_Ve6NezEoLtj-7GKAWuXOOEUXe0z9Bd-uKoZeBnE
code_challenge:
cmcJe_eAcSGnEema7PXUEDZZOSofeaUDhKJC5P--uOY
我的 article
中的其他信息