ASP.NET CORE 8.0 Microsoft Authentication Error - AuthenticationFailureException: состояние OAuth отсутствовало или недеC#

Место общения программистов C#
Ответить
Anonymous
 ASP.NET CORE 8.0 Microsoft Authentication Error - AuthenticationFailureException: состояние OAuth отсутствовало или неде

Сообщение Anonymous »

my setup:
  • App.net Core 8 MVC приложение, настроенное на действие чисто как API (возвращает JSON, без традиционных представлений)
  • Frontend: React Running on http: // localhost: 3000
  • Аутентификация учетной записи Microsoft, настроенная через AddMicrosoftAccount
  • идентификация основной идентификации пользователей
​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​

Код: Выделить всё

Program.cs
:

Код: Выделить всё

using AppBdsAPI.Data;
using AppBdsAPI.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;

var builder = WebApplication.CreateBuilder(args);

// Configurar logging para depuração
builder.Services.AddLogging(logging =>
{
logging.AddConsole();
logging.AddDebug();
logging.SetMinimumLevel(LogLevel.Debug);
});

// Configurar a string de conexão
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");

// Configurar o DbContext
builder.Services.AddDbContext(options =>
options.UseSqlServer(connectionString));

// Configurar o Identity com sua classe User personalizada
builder.Services.AddIdentity(options =>
{
options.SignIn.RequireConfirmedAccount = true;
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
})
.AddEntityFrameworkStores()
.AddDefaultTokenProviders()
.AddDefaultUI(); // Kept this as it's an MVC project, even if acting as API

// ====================================================================================
// COOKIE CONFIGURATION FOR EXTERNAL SCHEME (Attempt to fix SameSite issues)
// ====================================================================================
builder.Services.Configure(IdentityConstants.ExternalScheme, options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // Requires HTTPS
});
// ====================================================================================

// Configurar CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowFrontend", policy =>
{
policy.WithOrigins(
"https://localhost:3000"
)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});

// ====================================================================================
// MICROSOFT AUTHENTICATION CONFIGURATION
// ====================================================================================
builder.Services.AddAuthentication().AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.ClientId = builder.Configuration["Authentication:Microsoft:ClientId"];
microsoftOptions.ClientSecret = builder.Configuration["Authentication:Microsoft:ClientSecret"];
microsoftOptions.SignInScheme = IdentityConstants.ExternalScheme; // Explicitly setting SignInScheme
microsoftOptions.CallbackPath = "/auth/callback";  // Custom callback path
});
// ====================================================================================

// ====================================================================================
// RAZOR PAGES SERVICES (Kept as it's an MVC project)
// ====================================================================================
builder.Services.AddRazorPages();
// ====================================================================================

builder.Services.AddControllers();
builder.Services.AddControllersWithViews();

var app = builder.Build();

// ====================================================================================
// HOST HEADER OVERRIDE MIDDLEWARE (Currently commented out for production, not active for dev)
// ====================================================================================
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseMigrationsEndPoint();
}
else // Production
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();

/*
// This block is for production deployment with custom domains, not active locally.
app.Use((context, next) =>
{
context.Request.Host = new HostString("api.suaaplicacao.com");
context.Request.Scheme = "https";
return next();
});
*/
}
// ====================================================================================

// Habilitar middlewares na ordem correta
app.UseHttpsRedirection(); // Ensures HTTPS
app.UseStaticFiles();

app.UseCors("AllowFrontend");
app.UseRouting();

app.UseAuthentication(); // IMPORTANT: Before UseAuthorization
app.UseAuthorization();

app.MapControllers();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

app.MapRazorPages(); // IMPORTANT: If AddRazorPages() is used

// Add error endpoint for debugging
app.MapGet("/error", (string message) => Results.BadRequest(new { error = "OAuth error", message }));

app.Run();
< /code>
AuthController.cs
:

Код: Выделить всё

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using AppBdsAPI.Models;
using System.Security.Claims;
using Microsoft.EntityFrameworkCore;

[Route("auth")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly UserManager _userManager;

public AuthController(UserManager userManager)
{
_userManager = userManager;
}

// Endpoint to initiate Microsoft login
[HttpGet("login")]
public IActionResult Login()
{
var properties = new AuthenticationProperties
{
// Internal redirect URI after successful external authentication
RedirectUri = "/auth/callback"
};
return Challenge(properties, "Microsoft");
}

// Callback endpoint after external authentication
[HttpGet("callback")]
public async Task Callback()
{
// Authenticate using the external scheme
var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);

if (result?.Principal == null)
{
var errorMessage = result?.Failure?.Message ?? "Authentication failed.";
Console.WriteLine($"Authentication Error: {errorMessage}");
return BadRequest(new { error = errorMessage });
}

// Extract email from the principal
var email = result.Principal.FindFirst(ClaimTypes.Email)?.Value;

if (string.IsNullOrWhiteSpace(email))
{
Console.WriteLine("No email found in authentication result.");
return BadRequest(new { error = "Email not provided by Microsoft." });
}

// Validate email domain
if (!email.EndsWith("@ipt.pt"))
{
Console.WriteLine($"Invalid email domain: {email}");
return BadRequest(new { error = "Email must belong to @ipt.pt domain."  });
}

// Find or create user
var user = await _userManager.FindByEmailAsync(email);

if (user == null)
{
Console.WriteLine($"User not found for email: {email}");
return NotFound(new { error = "User not found." });
}

// Generate and save token
user.Token = Guid.NewGuid().ToString();
await _userManager.UpdateAsync(user);

var frontendRedirectUrl = $"http://localhost:3000/callback?token={user.Token}";
Console.WriteLine($"Redirecting to: {frontendRedirectUrl}");
return Redirect(frontendRedirectUrl);
}

// Logout endpoint
[HttpGet("logout")]
public async Task Logout(string returnUrl = "/")
{
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
return Redirect("http://localhost:3000/login");
}
}
< /code>
What I've already tried/checked:

[*]Azure AD Redirect URI: Confirmed that https://localhost:7253/auth/callback is precisely registered in my Azure AD App Registration (Application ID ad41e17a-362b-49db-82c8-dc7d5760efba). I've also tried /signin-microsoft with corresponding code changes, but the error persists.

[*]HTTPS: I am accessing the API via HTTPS (https://localhost:7253) throughout the entire login flow.

[*]Cookie SameSite Configuration: I've added builder.Services.Configure(IdentityConstants.ExternalScheme, ...)
с SameSitemode.none и securePolicy.always .

[*]

Код: Выделить всё

SignInScheme
: явно установите microsoftoptions.signinscheme = identityconstants.externalscheme;

[*]

Код: Выделить всё

AddDefaultUI()
и addrazorpages () : включено в них, поскольку решение представляет собой проект MVC, действующий в качестве API, чтобы обеспечить доступные механизмы внутреннего пользовательского интерфейса идентификации. app.usecors ()

[*] Кэш браузера/cookie: выполнил несколько полных кеша браузера и очистки cookie для localhost и microsoftonline.com и перезапустить браузер

restart restart. Применение после каждого изменения кода < /p>
< /li>
< /ul>
Несмотря на эти шаги, состояние «Oauth не хватало или неверная» сохраняется ошибка ». Мне интересно, есть ли у меня тонкое взаимодействие, или что redirecturi в аутентификации properties (

Код: Выделить всё

/auth/callback
) противоречит CallbackPath в addmicrosoftaccount (

Код: Выделить всё

/auth/callback
) каким -то неожиданным образом при использовании идентификации.
Любое понимание или предложения для дальнейшей отладки были бы очень оценены!

Подробнее здесь: https://stackoverflow.com/questions/796 ... eexception
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»