У меня есть настройка IdentityServer4 с шаблоном QuickStart для аутентификации пользователя против Micorosft Entra ID (с FIDO2). < /p>
IdentityServer4 получает обратно токен, и проверка начинается во extrualController.callback. Когда он Finnaly выполняет эту строку: < /p>
var principal = handler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
< /code>
Это не удалось с этим исключением: < /p>
idx10511: не удалась проверка подписи. Ключи пробовали:
'microsoft.identitymodel.tokens.x509SecurityKey, KeyId:
'mglqj10vnloxaffpjcbpgb4jaks', Internalid:
'mglqj10vnloxaffpjcbpgb4jaks'. , Keyid: mglqj10vnloxaffpjcbpgb4jaks
microsoft.identitymodel.tokens.rsasecurity, keyid:
'mglqj10vnloxaffpjcbpgb4jaks', internalid:
'Evi8giarv1jmmohnatij9o5mz_j_rthl2ego3upamq4'. , Keyid:
mglqj10vnloxaffpjcbpgb4jaks '. Количество ключей в
tokenvalidationparameters: '12'. Количество ключей в конфигурации:
'0'. Соответствующий ключ был в «TokenValidationParameters». Kid:
'mglqj10vnloxaffpjcbpgb4jaks'. Исключения поймали: ''. токен:
'retracted'. Подробнее см. Https://aka.ms/idx10511.builder.Service ... entication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect("Microsoft Entra ID", options =>
{
var microsoftEntraIdSettings = builder.Configuration.GetSection("MicrosoftEntraID").Get();
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.Authority = $"https://login.microsoftonline.com/{micr ... ntId}/v2.0";
options.ClientId = microsoftEntraIdSettings.ClientId;
options.ClientSecret = microsoftEntraIdSettings.ClientSecret;
options.ResponseType = "code";
options.SaveTokens = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.CallbackPath = "/signin-oidc";
options.Events = new OpenIdConnectEvents
{
OnRemoteFailure = context =>
{
// Log detailed error information
var error = context.Failure;
context.Response.Redirect("/Home/Error?message=" + error?.Message);
context.HandleResponse();
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
return Task.CompletedTask;
}
};
});
< /code>
Вот какой -то код от ExtressController: < /p>
[HttpGet]
public async Task Callback()
{
// read external identity from the temporary cookie
var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
var token = result.Properties.GetTokenValue("access_token");
var validatedToken = await ValidateTokenAsync(token);
if (validatedToken == null)
throw new Exception("Token validation failed");
if (_logger.IsEnabled(LogLevel.Debug))
{
var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
_logger.LogDebug("External claims: {@claims}", externalClaims);
}
// lookup our user and external provider info
var (user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
if (user == null)
{
// this might be where you might initiate a custom workflow for user registration
// in this sample we don't show how that would be done, as our sample implementation
// simply auto-provisions new external user
user = AutoProvisionUser(provider, providerUserId, claims);
}
// this allows us to collect any additional claims or properties
// for the specific protocols used and store them in the local auth cookie.
// this is typically used to store data needed for signout from those protocols.
var additionalLocalClaims = new List();
var localSignInProps = new AuthenticationProperties();
ProcessLoginCallback(result, additionalLocalClaims, localSignInProps);
// issue authentication cookie for user
var isuser = new IdentityServerUser(user.SubjectId)
{
DisplayName = user.Username,
IdentityProvider = provider,
AdditionalClaims = additionalLocalClaims
};
await HttpContext.SignInAsync(isuser, localSignInProps);
// delete temporary cookie used during external authentication
await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
// retrieve return URL
var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";
// check if external login is in the context of an OIDC request
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.Client.ClientId));
// The client is native, so this change in how to
// return the response is for better UX for the end user.
if (context != null && context.IsNativeClient())
return this.LoadingPage("Redirect", returnUrl);
return Redirect(returnUrl);
}
private async Task ValidateTokenAsync(string token)
{
var handler = new JwtSecurityTokenHandler();
IdentityModelEventSource.ShowPII = true;
IdentityModelEventSource.LogCompleteSecurityArtifact = true;
// Fetch the OpenID Connect configuration document
var config = await GetOpenIdConnectConfigurationAsync();
if (config == null || !config.SigningKeys.Any())
{
throw new Exception("No signing keys found in configuration");
}
// Extract the Key ID (kid) from the token header
var tokenKid = GetKidFromToken(token);
_logger.LogInformation("Token kid: {TokenKid}", tokenKid);
_logger.LogInformation("Config Signing Keys: {@Keys}", config.SigningKeys.Select(k => k.KeyId));
// Set up token validation parameters
var validationParameters = new TokenValidationParameters
{
ValidIssuer = $"https://login.microsoftonline.com/{_mic ... ntId}/v2.0",
ValidAudiences = new[] { _microsoftEntraIdSettings.ClientId },
IssuerSigningKeys = config.SigningKeys, //config.SigningKeys, // Use all keys from the configuration
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
ValidateTokenReplay = true,
ClockSkew = new TimeSpan(2, 0, 0),
// Additional logging for key retrieval
IssuerSigningKeyResolver = (token, securityToken, kid, validationParameters) =>
{
var keys = config.SigningKeys.Where(k => k.KeyId == kid).ToList();
_logger.LogInformation("Resolved keys for kid {Kid}: {@Keys}", kid, keys);
return keys;
}
};
try
{
// Validate the token using the matched public key
var principal = handler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
_logger.LogInformation("Token validated successfully");
return principal;
}
catch (Exception ex)
{
_logger.LogError(ex, "Token validation failed");
throw;
}
}
private async Task GetOpenIdConnectConfigurationAsync()
{
try
{
// Fetch the OpenID Connect configuration document from Microsoft Entra ID
var config = await _configurationManager.GetConfigurationAsync(CancellationToken.None);
_logger.LogInformation("Fetched OpenID Connect configuration: {@Config}", config);
return config;
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to fetch OpenID Connect configuration");
throw;
}
}
private string GetKidFromToken(string token)
{
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadJwtToken(token);
return jwtToken.Header.Kid;
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... a-id-fails
Проверьте токен от Microsoft Entra ID выходит из строя? ⇐ C#
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Как я могу получить токен MS Entra Identity в основном веб -API ASP.NET CORESPIPRINCIPAL?
Anonymous » » в форуме C# - 0 Ответы
- 3 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как я могу получить токен MS Entra Identity в основном веб -API ASP.NET CORESPIPRINCIPAL?
Anonymous » » в форуме C# - 0 Ответы
- 2 Просмотры
-
Последнее сообщение Anonymous
-