Configure Angular cookie using defaults from antiforgery options and fix logging

This commit is contained in:
Ronald Barendse
2023-11-15 16:08:57 +01:00
committed by Sebastiaan Janssen
parent c0e0e7bad8
commit e7f7492ce9

View File

@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
@@ -20,25 +22,35 @@ namespace Umbraco.Cms.Web.BackOffice.Security;
public class BackOfficeAntiforgery : IBackOfficeAntiforgery
{
private readonly IAntiforgery _internalAntiForgery;
private GlobalSettings _globalSettings;
private readonly CookieBuilder _angularCookieBuilder;
[Obsolete($"Please use the constructor that accepts {nameof(ILoggerFactory)}. Will be removed in V14.")]
public BackOfficeAntiforgery(IOptionsMonitor<GlobalSettings> globalSettings)
: this(globalSettings, NullLoggerFactory.Instance)
{ }
public BackOfficeAntiforgery(IOptionsMonitor<GlobalSettings> globalSettings, ILoggerFactory loggerFactory)
{
CookieSecurePolicy cookieSecurePolicy = globalSettings.CurrentValue.UseHttps ? CookieSecurePolicy.Always : CookieSecurePolicy.SameAsRequest;
// NOTE: This is the only way to create a separate IAntiForgery service :(
// Everything in netcore is internal. I have logged an issue here https://github.com/dotnet/aspnetcore/issues/22217
// but it will not be handled so we have to revert to this.
var services = new ServiceCollection();
services.AddLogging();
services.AddAntiforgery(x =>
{
x.HeaderName = Constants.Web.AngularHeadername;
x.Cookie.Name = Constants.Web.CsrfValidationCookieName;
x.Cookie.SecurePolicy = globalSettings.CurrentValue.UseHttps ? CookieSecurePolicy.Always : CookieSecurePolicy.SameAsRequest;
});
ServiceProvider container = services.BuildServiceProvider();
_internalAntiForgery = container.GetRequiredService<IAntiforgery>();
_globalSettings = globalSettings.CurrentValue;
globalSettings.OnChange(x => _globalSettings = x);
_internalAntiForgery = new ServiceCollection()
.AddSingleton(loggerFactory)
.AddAntiforgery(x =>
{
x.HeaderName = Constants.Web.AngularHeadername;
x.Cookie.Name = Constants.Web.CsrfValidationCookieName;
x.Cookie.SecurePolicy = cookieSecurePolicy;
})
.BuildServiceProvider()
.GetRequiredService<IAntiforgery>();
// Configure cookie builder using defaults from antiforgery options
_angularCookieBuilder = new AntiforgeryOptions().Cookie;
_angularCookieBuilder.HttpOnly = false; // Needs to be accessed from JavaScript
_angularCookieBuilder.SecurePolicy = cookieSecurePolicy;
}
/// <inheritdoc />
@@ -68,15 +80,6 @@ public class BackOfficeAntiforgery : IBackOfficeAntiforgery
// We need to set 2 cookies:
// The cookie value that angular will use to set a header value on each request - we need to manually set this here
// The validation cookie value generated by the anti-forgery helper that we validate the header token against - set above in GetAndStoreTokens
httpContext.Response.Cookies.Append(
Constants.Web.AngularCookieName,
set.RequestToken,
new CookieOptions
{
Path = "/",
//must be js readable
HttpOnly = false,
Secure = _globalSettings.UseHttps
});
httpContext.Response.Cookies.Append(Constants.Web.AngularCookieName, set.RequestToken, _angularCookieBuilder.Build(httpContext));
}
}