問題描述
我正在嘗試升級我的 MVC 網站以使用新的 OpenID Connect 標準.OWIN 中間件看起來很健壯,但不幸的是只支持form_post"響應類型.這意味著 Google 不兼容,因為它在#"之后返回 url 中的所有令牌,因此它們永遠不會到達服務器并且永遠不會觸發中間件.
I'm trying to upgrade my MVC website to use the new OpenID Connect standard. The OWIN middleware seems to be pretty robust, but unfortunately only supports the "form_post" response type. This means that Google isn't compatible, as it returns all the tokens in a the url after a "#", so they never reach the server and never trigger the middleware.
我自己嘗試觸發中間件中的響應處理程序,但這似乎根本不起作用,所以我有一個簡單的 javascript 文件,它解析返回的聲明并將它們發布到控制器操作進行處理.
I've tried to trigger the response handlers in the middleware myself, but that doesn't seem to work at all, so I've got a simply javascript file that parses out the returned claims and POSTs them to a controller action for processing.
問題是,即使我在服務器端獲取它們,我也無法正確解析它們.我得到的錯誤如下所示:
Problem is, even when I get them on the server side I can't parse them correctly. The error I get looks like this:
IDX10500: Signature validation failed. Unable to resolve
SecurityKeyIdentifier: 'SecurityKeyIdentifier
(
IsReadOnly = False,
Count = 1,
Clause[0] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause
),
token: '{
"alg":"RS256",
"kid":"073a3204ec09d050f5fd26460d7ddaf4b4ec7561"
}.
{
"iss":"accounts.google.com",
"sub":"100330116539301590598",
"azp":"1061880999501-b47blhmmeprkvhcsnqmhfc7t20gvlgfl.apps.googleusercontent.com",
"nonce":"7c8c3656118e4273a397c7d58e108eb1",
"email_verified":true,
"aud":"1061880999501-b47blhmmeprkvhcsnqmhfc7t20gvlgfl.apps.googleusercontent.com",
"iat":1429556543,"exp":1429560143
}'."
}
我的令牌驗證碼遵循開發 IdentityServer 的好人概述的示例
My token verification code follows the example outlined by the good people developing IdentityServer
private async Task<IEnumerable<Claim>> ValidateIdentityTokenAsync(string idToken, string state)
{
// New Stuff
var token = new JwtSecurityToken(idToken);
var jwtHandler = new JwtSecurityTokenHandler();
byte[][] certBytes = getGoogleCertBytes();
for (int i = 0; i < certBytes.Length; i++)
{
var certificate = new X509Certificate2(certBytes[i]);
var certToken = new X509SecurityToken(certificate);
// Set up token validation
var tokenValidationParameters = new TokenValidationParameters();
tokenValidationParameters.ValidAudience = googleClientId;
tokenValidationParameters.IssuerSigningToken = certToken;
tokenValidationParameters.ValidIssuer = "accounts.google.com";
try
{
// Validate
SecurityToken jwt;
var claimsPrincipal = jwtHandler.ValidateToken(idToken, tokenValidationParameters, out jwt);
if (claimsPrincipal != null)
{
// Valid
idTokenStatus = "Valid";
}
}
catch (Exception e)
{
if (idTokenStatus != "Valid")
{
// Invalid?
}
}
}
return token.Claims;
}
private byte[][] getGoogleCertBytes()
{
// The request will be made to the authentication server.
WebRequest request = WebRequest.Create(
"https://www.googleapis.com/oauth2/v1/certs"
);
StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
string responseFromServer = reader.ReadToEnd();
String[] split = responseFromServer.Split(':');
// There are two certificates returned from Google
byte[][] certBytes = new byte[2][];
int index = 0;
UTF8Encoding utf8 = new UTF8Encoding();
for (int i = 0; i < split.Length; i++)
{
if (split[i].IndexOf(beginCert) > 0)
{
int startSub = split[i].IndexOf(beginCert);
int endSub = split[i].IndexOf(endCert) + endCert.Length;
certBytes[index] = utf8.GetBytes(split[i].Substring(startSub, endSub).Replace("\n", "
"));
index++;
}
}
return certBytes;
}
我知道簽名驗證對于 JWT 來說并不是完全必要的,但我一點也不知道如何關閉它.有什么想法嗎?
I know that Signature validation isn't completely necessary for JWTs but I haven't the slightest idea how to turn it off. Any ideas?
推薦答案
問題是JWT中的kid
,其值為key的key標識符,用于簽署JWT.由于您從 JWKs URI 手動構造了一組證書,因此您丟失了密鑰標識符信息.然而,驗證過程需要它.
The problem is the kid
in the JWT whose value is the key identifier of the key was used to sign the JWT. Since you construct an array of certificates manually from the JWKs URI, you lose the key identifier information. The validation procedure however requires it.
您需要將 tokenValidationParameters.IssuerSigningKeyResolver
設置為一個函數,該函數將返回您上面在 tokenValidationParameters.IssuerSigningToken
中設置的相同密鑰.此委托的目的是指示運行時忽略任何匹配"語義并嘗試密鑰.
You'll need to set tokenValidationParameters.IssuerSigningKeyResolver
to a function that will return the same key that you set above in tokenValidationParameters.IssuerSigningToken
. The purpose of this delegate is to instruct the runtime to ignore any 'matching' semantics and just try the key.
有關更多信息,請參閱本文:JwtSecurityTokenHandler 4.0.0 重大更改?
See this article for more information: JwtSecurityTokenHandler 4.0.0 Breaking Changes?
代碼:
tokenValidationParameters.IssuerSigningKeyResolver = (token, securityToken, kid, validationParameters) => { return new X509SecurityKey(certificate); };
這篇關于驗證 Google OpenID Connect JWT ID 令牌的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!