[MN-04] Identity: Fix Google Callback Error Handling and Logging #18

Merged
mjasin merged 1 commits from fix/issue-3-identity-callback-errors into develop 2026-05-07 17:27:40 +00:00
2 changed files with 47 additions and 2 deletions
@@ -90,11 +90,30 @@
</div>
@code {
[Parameter]
[SupplyParameterFromQuery(Name = "error")]
public string? ErrorCode { get; set; }
private LoginModel _loginModel = new();
private string? _errorMessage;
private bool _isSubmitting;
private bool _showPassword;
protected override void OnInitialized()
{
if (!string.IsNullOrEmpty(ErrorCode))
{
_errorMessage = ErrorCode switch
{
"ExternalLoginFailed" => "Nie udało się zalogować przez Google. Spróbuj ponownie.",
"ProvisioningFailed" => "Wystąpił błąd podczas przygotowywania Twojego konta.",
"UserAlreadyExists" => "Użytkownik o tym adresie e-mail już istnieje. Zaloguj się tradycyjnie hasłem.",
"LockedOut" => "Twoje konto zostało zablokowane. Spróbuj ponownie później.",
_ => "Wystąpił nieoczekiwany błąd podczas logowania."
};
}
}
private async Task HandleLogin()
{
_isSubmitting = true;
+28 -2
View File
@@ -355,31 +355,57 @@ app.MapGet("/identity/login/google", (string? returnUrl) =>
app.MapGet("/identity/callback/google", async (
HttpContext context,
SignInManager<NexusUser> signInManager,
UserManager<NexusUser> userManager) =>
UserManager<NexusUser> userManager,
ILogger<Program> logger) =>
{
var info = await signInManager.GetExternalLoginInfoAsync();
if (info == null) return Results.Redirect("/account/login?error=ExternalLoginFailed");
if (info == null)
{
logger.LogWarning("External login info from Google is null.");
return Results.Redirect("/account/login?error=ExternalLoginFailed");
}
var result = await signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
if (result.Succeeded)
{
logger.LogInformation("User logged in via Google: {Email}", info.Principal.FindFirstValue(ClaimTypes.Email));
return Results.Redirect("/");
}
if (result.IsLockedOut)
{
logger.LogWarning("User account locked out during Google login: {Email}", info.Principal.FindFirstValue(ClaimTypes.Email));
return Results.Redirect("/account/login?error=LockedOut");
}
// New user provisioning
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
if (email != null)
{
var user = new NexusUser { UserName = email, Email = email, EmailConfirmed = true };
var createResult = await userManager.CreateAsync(user);
if (createResult.Succeeded)
{
await userManager.AddLoginAsync(user, info);
await signInManager.SignInAsync(user, isPersistent: false);
logger.LogInformation("New user provisioned via Google: {Email}", email);
return Results.Redirect("/");
}
// Log specific errors
foreach (var error in createResult.Errors)
{
logger.LogError("Google provisioning failed for {Email}: {Code} - {Description}", email, error.Code, error.Description);
}
if (createResult.Errors.Any(e => e.Code == "DuplicateEmail" || e.Code == "DuplicateUserName"))
{
return Results.Redirect("/account/login?error=UserAlreadyExists");
}
}
logger.LogError("Google provisioning failed - unknown reason for email {Email}", email);
return Results.Redirect("/account/login?error=ProvisioningFailed");
});