< /ul>
Der Token selbst ist nicht veränderter und manuelles Inspektion bestätigt, dass die Anhänger, die Zahlung und die Schild, die alle ordnungsgemäß formuliert sind, gebildet werden. Das Problem tritt beim Versuch auf, die Signatur des Token zu validieren. Meine Konfiguration für Anwendungstoken funktioniert einwandfrei, aber Benutzer-Token schließen fehl.
Code: Select all
.AddScheme(
CISAuthorityTypes.UserAuthenticationType,
(o) => {
//var validAudience = cisAuthenticationOptions.ApplicationIdentityAudience;
o.Challenge = CISAuthorityTypes.UserAuthenticationType;
//o.Audience = validAudience;
o.IncludeErrorDetails = isDevelopmentMode;
o.RequireHttpsMetadata = isDevelopmentMode;
o.Authority = msOnlineAuthority.ToString();
o.ConfigurationManager = configurationManager;
string[] allowedIssuers = ["https://sts.windows.net/", "https://login.microsoftonline.com/"];
o.TokenValidationParameters = new TokenValidationParameters() {
ValidateAudience = false,
//ValidAudience = validAudience,
//ValidateLifetime = true,
ValidateIssuer = false,
IssuerSigningKeys = keys,
TryAllIssuerSigningKeys = false,
ValidateIssuerSigningKey = false,
LogValidationExceptions = isDevelopmentMode,
ValidateSignatureLast = false,
NameClaimType = CISClaimTypes.NameClaimName,
RoleClaimType = CISClaimTypes.RoleClaimName,
////IssuerSigningKeyValidatorUsingConfiguration = null, // TODO
////IssuerSigningKeyResolver = null, // TODO
AuthenticationType = CISAuthorityTypes.UserAuthenticationType,
#region TODO REMOVE DEBUG BLOCK
//SignatureValidator = (token, parameters) => {
// var tokenHandler = new JwtSecurityTokenHandler();
// var innerJwt = new JwtSecurityToken(token);
// if (parameters.IssuerSigningKeys != null) {
// var keys = (from i in parameters.IssuerSigningKeys
// where i.KeyId == innerJwt.Header.Kid
// select i).ToArray();
// foreach (var key in keys) {
// if (key is RsaSecurityKey keyAsRsaSecKey) {
// JwtSignatureValidator.ValidateSignature(keyAsRsaSecKey, token, null);
// } else {
// JwtSignatureValidator.ValidateSignature((X509SecurityKey)key, token, null);
// }
// //try {
// // // Create a copy of the parameters with only this key
// // var singleKeyParameters = parameters.Clone();
// // singleKeyParameters.IssuerSigningKey = key;
// // singleKeyParameters.IssuerSigningKeys = new[] { key };
// // singleKeyParameters.SignatureValidator = null;
// // // This will throw if the signature validation fails.
// // SecurityToken validatedToken;
// // tokenHandler.ValidateToken(token, singleKeyParameters, out validatedToken);
// // // If validation succeeded, return the validated token.
// // return validatedToken;
// //} catch (SecurityTokenInvalidSignatureException) {
// // // Try the next key if the current key fails.
// //}
// }
// }
// return innerJwt;
//},
#endregion
IssuerValidator = (issuer, securityToken, parameters) => {
var q = from i in allowedIssuers
where issuer.StartsWith(i, StringComparison.OrdinalIgnoreCase)
select i;
if (q.Any()) {
var jwtToken = (JwtSecurityToken)securityToken;
var tempPrincipal = new ClaimsPrincipal(new ClaimsIdentity(jwtToken.Claims, CISAuthorityTypes.UserAuthenticationType));
if (CISJwtSecurityTokenValidator.ValidateUser(tempPrincipal))
return issuer;
}
throw new SecurityTokenInvalidIssuerException("Invalid issuer.");
}
};
}
)
< /code>
Ich habe eine Testklasse hinzugefügt, um die Validierung des Tokens zu überprüfen.
Es bestätigt auch, dass die Validierung fehlschlägt. Hier sind die beiden Validierungsmethoden, die sowohl rsasecurityKey
Hinweis : Der hier gezeigte Code wird als Troublshooting -Klasse bereitgestellt, um das Access_Token gegen den Schlüssel zu überprüfen. Es wird über die Tokenvalidationsparameter angewendet.
Code: Select all
// TODO: Remove this debug class
public static class JwtSignatureValidator
{
///
/// Validates the signature of a JWT using an RsaSecurityKey.
///
///
The RsaSecurityKey to use for validation.
/// The JWT token string.
/// True if the signature is valid; otherwise, false.
public static bool ValidateSignature(RsaSecurityKey key, string token)
{
var parts = token.Split('.');
if (parts.Length != 3)
throw new ArgumentException("Invalid JWT token format.", nameof(token));
// JWT signing input is the header and payload parts concatenated with a period.
string signingInput = $"{parts[0]}.{parts[1]}";
byte[] signingBytes = Encoding.UTF8.GetBytes(signingInput);
byte[] signature = Base64UrlDecode(parts[2]);
// Get the RSA instance from the key.
RSA rsa = key.Rsa;
if (rsa == null)
{
rsa = RSA.Create();
rsa.ImportParameters(key.Parameters);
}
// Verify the signature with SHA256 and PKCS#1 v1.5 padding.
var returnValue = rsa.VerifyData(signingBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
// Redundant re-verification with the same padding.
returnValue = rsa.VerifyData(signingBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
return returnValue;
}
///
/// Validates the signature of a JWT using an X509SecurityKey.
///
/// The X509SecurityKey to use for validation.
/// The JWT token string.
/// True if the signature is valid; otherwise, false.
public static bool ValidateSignature(X509SecurityKey key, string token)
{
var parts = token.Split('.');
if (parts.Length != 3)
throw new ArgumentException("Invalid JWT token format.", nameof(token));
string signingInput = $"{parts[0]}.{parts[1]}";
byte[] signingBytes = Encoding.UTF8.GetBytes(signingInput);
byte[] signature = Base64UrlDecode(parts[2]);
// Extract the RSA public key from the certificate.
var certificate = key.Certificate;
using (RSA rsa = certificate.GetRSAPublicKey())
{
var returnValue = rsa.VerifyData(signingBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
// Additional verification using RSASignaturePadding.Pss is performed here.
returnValue = rsa.VerifyData(signingBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
return returnValue;
}
}
///
/// Decodes a Base64Url-encoded string.
///
/// The Base64Url-encoded string.
/// The decoded byte array.
private static byte[] Base64UrlDecode(string input)
{
string padded = input.Replace('-', '+').Replace('_', '/');
switch (padded.Length % 4)
{
case 2: padded += "=="; break;
case 3: padded += "="; break;
}
return Convert.FromBase64String(padded);
}
}
Hat jemand ein ähnliches Problem mit Azure Entra ID -Token, trotz der Tastenübereinstimmungen fehlgeschlagen? Könnte es im Token -Unterzeichnungsprozess oder in der Art und Weise, wie das Zertifikat verwendet wird, Nuancen geben, die dies verursachen könnte? Alle Anleitungen zu Best Practices zur Überprüfung dieser Token wären sehr geschätzt.
Vielen Dank im Voraus für Ihre Hilfe!