fix: redirect_uri ms
All checks were successful
BCards Deployment Pipeline / Run Tests (pull_request) Successful in 2s
BCards Deployment Pipeline / PR Validation (pull_request) Successful in 0s
BCards Deployment Pipeline / Build and Push Image (pull_request) Has been skipped
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (pull_request) Has been skipped
BCards Deployment Pipeline / Deploy to Staging (x86 - Local) (pull_request) Has been skipped
BCards Deployment Pipeline / Cleanup Old Resources (pull_request) Has been skipped
BCards Deployment Pipeline / Deployment Summary (pull_request) Successful in 0s

This commit is contained in:
Ricardo Carneiro 2025-08-21 21:50:04 -03:00
parent e727ffdedc
commit def712bffe

View File

@ -3,10 +3,12 @@ using BCards.Web.Services;
using BCards.Web.Repositories; using BCards.Web.Repositories;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using MongoDB.Driver; using MongoDB.Driver;
using System.Globalization; using System.Globalization;
using Stripe;
using Microsoft.AspNetCore.Authentication.OAuth; using Microsoft.AspNetCore.Authentication.OAuth;
using SendGrid; using SendGrid;
using BCards.Web.Middleware; using BCards.Web.Middleware;
@ -15,6 +17,17 @@ using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// 🔥 CONFIGURAR FORWARDED HEADERS NO BUILDER
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
options.RequireHeaderSymmetry = false;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
// 🚨 PERMITIR QUALQUER PROXY (NGINX)
options.ForwardLimit = null;
});
// Add services to the container. // Add services to the container.
builder.Services.AddControllersWithViews() builder.Services.AddControllersWithViews()
.AddRazorRuntimeCompilation() .AddRazorRuntimeCompilation()
@ -83,23 +96,43 @@ builder.Services.AddAuthentication(options =>
options.AuthorizationEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"; options.AuthorizationEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
options.TokenEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/token"; options.TokenEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
// 🔥 SOLUÇÃO RADICAL: SEMPRE FORÇAR HTTPS
options.Events = new OAuthEvents options.Events = new OAuthEvents
{ {
OnRedirectToAuthorizationEndpoint = context => OnRedirectToAuthorizationEndpoint = context =>
{ {
// 1. Força HTTPS em produção var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>();
if (!builder.Environment.IsDevelopment())
// Debug info
logger.LogWarning($"=== MICROSOFT AUTH DEBUG ===");
logger.LogWarning($"Original RedirectUri: {context.RedirectUri}");
logger.LogWarning($"Request Scheme: {context.Request.Scheme}");
logger.LogWarning($"Request IsHttps: {context.Request.IsHttps}");
logger.LogWarning($"Request Host: {context.Request.Host}");
logger.LogWarning($"X-Forwarded-Proto: {context.Request.Headers["X-Forwarded-Proto"]}");
// 🚨 FORÇA HTTPS SEMPRE (exceto localhost)
var originalUri = context.RedirectUri;
// Se contém bcards.site, força HTTPS
if (originalUri.Contains("bcards.site"))
{ {
context.RedirectUri = context.RedirectUri.Replace("http://", "https://"); context.RedirectUri = originalUri
.Replace("http://bcards.site", "https://bcards.site")
.Replace("http%3A%2F%2Fbcards.site", "https%3A%2F%2Fbcards.site");
logger.LogWarning($"FORCED HTTPS - Modified RedirectUri: {context.RedirectUri}");
} }
// 2. Adiciona prompt=login para forçar seleção de conta // Adiciona prompt=login para forçar seleção de conta
var redirectUri = context.RedirectUri; var redirectUri = context.RedirectUri;
if (!redirectUri.Contains("prompt=")) if (!redirectUri.Contains("prompt="))
{ {
redirectUri += "&prompt=login"; redirectUri += "&prompt=login";
} }
logger.LogWarning($"Final RedirectUri: {redirectUri}");
context.Response.Redirect(redirectUri); context.Response.Redirect(redirectUri);
return Task.CompletedTask; return Task.CompletedTask;
} }
@ -127,7 +160,7 @@ builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<IUserPageRepository, UserPageRepository>(); builder.Services.AddScoped<IUserPageRepository, UserPageRepository>();
builder.Services.AddScoped<ICategoryRepository, CategoryRepository>(); builder.Services.AddScoped<ICategoryRepository, CategoryRepository>();
builder.Services.AddScoped<ISubscriptionRepository, SubscriptionRepository>(); builder.Services.AddScoped<ISubscriptionRepository, SubscriptionRepository>();
builder.Services.AddSingleton<IModerationAuthService, ModerationAuthService>(); builder.Services.AddSingleton<IModerationAuthService, ModerationAuthService>();
//builder.Services.AddScoped<IModerationAuthService, ModerationAuthService>(); //builder.Services.AddScoped<IModerationAuthService, ModerationAuthService>();
builder.Services.AddScoped<IUserPageService, UserPageService>(); builder.Services.AddScoped<IUserPageService, UserPageService>();
@ -177,14 +210,26 @@ builder.Services.AddRazorPages();
var app = builder.Build(); var app = builder.Build();
app.UseForwardedHeaders(new ForwardedHeadersOptions // 🔥 PRIMEIRA COISA APÓS BUILD - FORWARDED HEADERS + BASE URL OVERRIDE
app.UseForwardedHeaders();
// 🚨 FORÇA BASE URL HTTPS EM PRODUÇÃO
if (!app.Environment.IsDevelopment())
{ {
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto, app.Use(async (context, next) =>
// Permitir qualquer proxy (necessário para NGINX) {
RequireHeaderSymmetry = false, // Força o contexto a pensar que está em HTTPS
KnownNetworks = { }, context.Request.Scheme = "https";
KnownProxies = { }
}); // Override do Host se necessário
if (context.Request.Host.Host == "bcards.site")
{
context.Request.Host = new HostString("bcards.site", 443);
}
await next();
});
}
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment()) if (!app.Environment.IsDevelopment())
@ -209,12 +254,38 @@ app.UseMiddleware<BCards.Web.Middleware.PageStatusMiddleware>();
app.UseMiddleware<BCards.Web.Middleware.PreviewTokenMiddleware>(); app.UseMiddleware<BCards.Web.Middleware.PreviewTokenMiddleware>();
app.UseMiddleware<ModerationAuthMiddleware>(); app.UseMiddleware<ModerationAuthMiddleware>();
// 🔥 DEBUG MIDDLEWARE MELHORADO
app.Use(async (context, next) => app.Use(async (context, next) =>
{ {
// Debug geral
Console.WriteLine($"=== REQUEST DEBUG ==="); Console.WriteLine($"=== REQUEST DEBUG ===");
Console.WriteLine($"Path: {context.Request.Path}"); Console.WriteLine($"Path: {context.Request.Path}");
Console.WriteLine($"Query: {context.Request.QueryString}"); Console.WriteLine($"Query: {context.Request.QueryString}");
Console.WriteLine($"Method: {context.Request.Method}"); Console.WriteLine($"Method: {context.Request.Method}");
Console.WriteLine($"Scheme: {context.Request.Scheme}");
Console.WriteLine($"IsHttps: {context.Request.IsHttps}");
Console.WriteLine($"Host: {context.Request.Host}");
// Debug específico para Microsoft signin
if (context.Request.Path.StartsWithSegments("/signin-microsoft"))
{
var logger = context.RequestServices.GetRequiredService<ILogger<Program>>();
logger.LogWarning($"=== SIGNIN-MICROSOFT CALLBACK DEBUG ===");
logger.LogWarning($"Path: {context.Request.Path}");
logger.LogWarning($"Query: {context.Request.QueryString}");
logger.LogWarning($"Method: {context.Request.Method}");
logger.LogWarning($"Scheme: {context.Request.Scheme}");
logger.LogWarning($"IsHttps: {context.Request.IsHttps}");
logger.LogWarning($"Host: {context.Request.Host}");
logger.LogWarning($"X-Forwarded-Proto: {context.Request.Headers["X-Forwarded-Proto"]}");
logger.LogWarning($"X-Forwarded-For: {context.Request.Headers["X-Forwarded-For"]}");
logger.LogWarning($"All Headers:");
foreach (var header in context.Request.Headers)
{
logger.LogWarning($" {header.Key}: {header.Value}");
}
}
await next(); await next();
}); });
@ -260,13 +331,12 @@ app.MapControllerRoute(
name: "default", name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"); pattern: "{controller=Home}/{action=Index}/{id?}");
// Initialize default data // Initialize default data
using (var scope = app.Services.CreateScope()) using (var scope = app.Services.CreateScope())
{ {
var themeService = scope.ServiceProvider.GetRequiredService<IThemeService>(); var themeService = scope.ServiceProvider.GetRequiredService<IThemeService>();
var categoryService = scope.ServiceProvider.GetRequiredService<ICategoryService>(); var categoryService = scope.ServiceProvider.GetRequiredService<ICategoryService>();
try try
{ {
// Initialize themes // Initialize themes
@ -275,7 +345,7 @@ using (var scope = app.Services.CreateScope())
{ {
await themeService.InitializeDefaultThemesAsync(); await themeService.InitializeDefaultThemesAsync();
} }
// Initialize categories // Initialize categories
var existingCategories = await categoryService.GetAllCategoriesAsync(); var existingCategories = await categoryService.GetAllCategoriesAsync();
if (!existingCategories.Any()) if (!existingCategories.Any())
@ -293,4 +363,4 @@ using (var scope = app.Services.CreateScope())
app.Run(); app.Run();
// Make Program accessible for integration tests // Make Program accessible for integration tests
public partial class Program { } public partial class Program { }