Sto tentando di aggiornare il sito Web MVC per utilizzare il nuovo standard OpenID Connect. Il middleware OWIN sembra essere piuttosto robusto, ma sfortunatamente supporta solo il tipo di risposta "form_post" . Ciò significa che Google non è compatibile, poiché restituisce tutti i token nell'URL dopo un "#", in modo che non raggiungano mai il server e non attivino mai il middleware.Convalida il token ID JWT di OpenID Connect di Google
Ho provato ad attivare i gestori di risposta nel middleware, ma non sembra funzionare affatto, quindi ho un semplice file javascript che analizza le attestazioni restituite e le invia POST a un controller azione per l'elaborazione.
Il problema è che, anche quando li ottengo sul lato server, non posso analizzarli correttamente. L'errore che ottengo appare così:
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
}'."
}
mio codice di verifica di token segue l'esempio tracciato dalle buone persone in via di sviluppo 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", "\n"));
index++;
}
}
return certBytes;
}
so che la convalida della firma non è del tutto necessaria per JWTs ma io non ho la minima idea di come spegnerlo. Qualche idea?
Una volta ho capito come si fa, questo ha funzionato perfettamente. Grazie per l'aiuto. Il codice si presenta così: 'tokenValidationParameters.IssuerSigningKeyResolver = (arbitrariamente, dichiarando, questi, parametri) => { return new X509SecurityKey (certificato); }; ' – ReimTime
thx, aggiunto alla risposta per completezza –