.NET 6: корреляционные файлы cookie теряются за обратным прокси-сервером после аутентификацииC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 .NET 6: корреляционные файлы cookie теряются за обратным прокси-сервером после аутентификации

Сообщение Anonymous »

У меня возникла проблема с моим приложением .NET 6: файлы cookie корреляции теряются после аутентификации при развертывании за обратным прокси-сервером. Обратный прокси-сервер обрабатывает HTTPS, поэтому само приложение не управляет HTTPS напрямую.
Приложение работает правильно при локальном запуске, но в производственной среде (за обратным прокси-сервером) корреляция файлы cookie теряются после аутентификации.

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

var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddConsole();
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();

builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});

string SecurityLevelClaimPolicy = "SecurityLevelClaimPolicy";
string SecurityLevelClaim = "Claims";
Settings _settings = new Settings();
_settings.IdConfiguration = new IdConfiguration();
//_settings.ClientType = ClientType.ApiAccess;

_settings.ClientType = ClientType.ApiAccessForMultiTenantClient;
_settings.ApiAudience1 = "URL";
_settings.IdConfiguration = new IdConfiguration();
_settings.IdConfiguration.ClientId = "clientid";
_settings.IdConfiguration.RsaPrivateKeyJwk = new TestIT.Authenticator.API.Helpers.SecurityKey("{'d':'XXXXXX','kid':'XXXXXX','use':'XXXXX','alg':'XXXXX'}", "XXXXX");
_settings.IdConfiguration.Scope = "scope";
_settings.IdConfiguration.StsUrl = "URL";

builder.Services.AddHttpContextAccessor();

builder.Services.AddMvc()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = new LowercaseContractResolver();
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.Converters.Add(new TestIT.Authenticator.API.Helpers.DateTimeHelper("dd.MM.yyyyTHH.mm.ss"));
})
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, opts =>
{
opts.ResourcesPath = "Resources";
})
.AddDataAnnotationsLocalization();

builder.Services.AddControllers();
builder.Services.AddRouting(options => options.LowercaseUrls = true);
builder.Services.AddEndpointsApiExplorer();
builder.Services.Configure(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.None;
options.Secure = CookieSecurePolicy.Always; // Ensure cookies are marked as Secure
});

// Create a settings instance.  These can be injected into other objects, for instance the HomeController
builder.Services.AddSingleton(_settings);
// We need the IdConfiguration instance as a service as well:
builder.Services.AddSingleton(_settings.IdConfiguration);

// Services for calculating the expiration time for tokens
var dateTimeService = new DateTimeService();
builder.Services.AddSingleton(dateTimeService);
builder.Services.AddTransient();
builder.Services.AddSingleton();

// No request object is needed, so we inject a null object for payload claims creation instead
builder.Services.AddSingleton(new NullPayloadClaimsCreatorForRequestObjects());

//var clientAssertionPayloadClaimsCreator = new ClientAssertionPayloadClaimsCreator(dateTimeService);
//builder.Services.AddSingleton(clientAssertionPayloadClaimsCreator);

var clientAssertionPayloadClaimsCreator = new ClientAssertionPayloadClaimsCreator(dateTimeService);

// We need payload claims for the token request, both the "default" type and for the multi-tenant organization number:
var compositePayloadClaimsCreator = new CompositePayloadClaimsCreator(new List
{
clientAssertionPayloadClaimsCreator,
new PayloadClaimsCreatorForMultiTenantClient()
});
// We add this object as an instance of IPayloadClaimsCreatorForClientAssertion
builder.Services.AddSingleton(compositePayloadClaimsCreator);

builder.Services.AddTransient();

builder.Services.AddSingleton();

builder.Services.AddTransient();
// Builder for client assertions payloads
// Builder for JWT tokens used for client assertions
builder.Services.AddSingleton(new DiscoveryDocumentGetter(_settings.IdConfiguration.StsUrl));
builder.Services.AddSingleton();
// Builds token requests (in our case, refresh token requests)
builder.Services.AddTransient();
// Register services here

builder.Services.AddTransient();
builder.Services.AddScoped();
// A getter of user session data, uses the user session data store
builder.Services.AddTransient();

builder.Services.AddAuthentication(options =>
{
// Configure default authentication schemes for the application
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
//options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
// Configure JWT bearer authentication
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.GetValue("Secret"))),
ValidateIssuer = true,
ValidIssuer = config.GetValue("Issuer"),
ValidateAudience = true,
ValidAudience = config.GetValue("Audience"),
ValidateLifetime = true,
};
});

builder.Services.AddSwaggerGen(c =>
{
// Configure Swagger documentation
c.SwaggerDoc("v1", new OpenApiInfo { Title = "TestIt .Net middleware", Version = "v1"  });

// Add JWT bearer authentication to Swagger
var securityScheme = new OpenApiSecurityScheme
{
Name = "Authorization",
BearerFormat = "JWT",
Scheme = "bearer",
Description = "JWT Authorization header using the Bearer scheme.",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
};
c.AddSecurityDefinition("Bearer", securityScheme);
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty()
}
});
});

builder.Services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // Ensure cookies are sent over HTTPS
options.Cookie.SameSite = SameSiteMode.None; // Set the SameSite attribute to None
});

builder.Services.AddTransient();
builder.Services.AddTransient();
builder.Services.AddTransient();
builder.Services.Configure(OpenIdConnectOptions =>
{
OpenIdConnectOptions.MinimumSameSitePolicy = SameSiteMode.None;
OpenIdConnectOptions.Secure = CookieSecurePolicy.Always; // Ensure cookies are marked as Secure
});
//// Set authentication options (these will call the AuthenticationOptionsInitializer and OpenIdConnectOptionsInitializer instances)
builder.Services.AddAuthentication()
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectOptions =>
{
// Path to access denied endpoint. Used when authorization fails
OpenIdConnectOptions.AccessDeniedPath = "/authorization/access-denied";
OpenIdConnectOptions.AccessDeniedPath = "/authorization/access-denied";

// Ensure cookies are only sent over HTTPS
OpenIdConnectOptions.Cookie.SecurePolicy = CookieSecurePolicy.Always;

// Set SameSite policy.  Adjust as necessary based on your requirements
OpenIdConnectOptions.Cookie.SameSite = SameSiteMode.None;

// Mark the cookie as HttpOnly
OpenIdConnectOptions.Cookie.HttpOnly = true;
})
.AddOpenIdConnect(openIdConnectOptions =>
{
// We need to extract the OpenID Connect options initializer from the service provider:
var serviceProvider = builder.Services.BuildServiceProvider();
var initializer = serviceProvider.GetService();
initializer!.Configure(nameof(UserAuthendication), openIdConnectOptions);
openIdConnectOptions.CallbackPath = "/signin-oidc";
openIdConnectOptions.NonceCookie.SecurePolicy = CookieSecurePolicy.Always;
openIdConnectOptions.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always;

});

var securityLevelClaimPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireClaim(IdSecurityLevelClaim, "4")
.Build();

builder.Services.AddDataProtection();
builder.Services.AddAuthorization(config =>
{
config.AddPolicy(SecurityLevelClaimPolicy, securityLevelClaimPolicy);
});
var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");

}

app.UseRouting();

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedFor | Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedProto
});
app.UseCookiePolicy(new CookiePolicyOptions
{
Secure = CookieSecurePolicy.Always,

});

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

//app.UseHttpsRedirection();

app.UseCors("AllowAll");
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();
Есть ли что-то, что мне не хватает в конфигурации, что может привести к потере корреляционных файлов cookie после аутентификации? Будем очень признательны за любые советы и идеи.
Изменить: забыл упомянуть, что приложение находится внутри контейнера докеров

Подробнее здесь: https://stackoverflow.com/questions/788 ... entication
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

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