Skip to content

Commit

Permalink
cleanup cookie container creation
Browse files Browse the repository at this point in the history
  • Loading branch information
NielsPilgaard committed Feb 24, 2024
1 parent f7de910 commit 2b94993
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public static class CircuitHandlerExtensions
public static IServiceCollection AddCurrentUser(this IServiceCollection services)
{
services.AddScoped<CurrentUser>();
services.AddScoped<CookieContainerFactory>();
services.TryAddEnumerable(ServiceDescriptor.Scoped<CircuitHandler, UserCircuitHandler>());
return services;
}
Expand Down
73 changes: 73 additions & 0 deletions src/web/Jordnaer/Features/Authentication/CookieContainerFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System.Net;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;

namespace Jordnaer.Features.Authentication;

public sealed class CookieContainerFactory(
ILogger<CookieContainerFactory> logger,
IServer server,
CurrentUser currentUser)
{
public CookieContainer? Create()
{
if (currentUser.Id is null)
{
logger.LogDebug("CurrentUser is not logged in, cannot create an authenticated SignalR Connection.");
return null;
}

if (currentUser.Cookie is null)
{
logger.LogWarning("CurrentUser {UserId} does not have a cookie, cannot create an authenticated SignalR Connection.", currentUser.Id);
return null;
}

var allServerUris = server.Features.Get<IServerAddressesFeature>()?.Addresses;
logger.LogDebug("All server addresses: {@ServerAddresses}", allServerUris);

var serverUri = server.Features.Get<IServerAddressesFeature>()?.Addresses.FirstOrDefault();
if (serverUri is null)
{
logger.LogError("Failed to get server address from IServer");
return null;
}

var cookieContainer = new CookieContainer(1);

if (!serverUri.Contains("[::]"))
{
cookieContainer.Add(CreateCookie(new Uri(serverUri).Host));
return cookieContainer;
}

logger.LogInformation(
"First server address was {ServerUri}, trying to get hostname from environment variable 'WEBSITE_HOSTNAME' instead.", serverUri);

var domain = Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME");
if (domain is null)
{
logger.LogError("Cannot determine domain for Cookie, " +
"environment variable 'WEBSITE_HOSTNAME' was null.");
return null;
}

cookieContainer.Add(CreateCookie(domain));

return cookieContainer;
}

private Cookie CreateCookie(string domain)
{
logger.LogInformation("Creating cookie with domain {Domain}", domain);

return new Cookie(name: AuthenticationConstants.CookieName,
value: currentUser.Cookie,
path: "/",
domain: domain)
{
Secure = true,
HttpOnly = true
};
}
}
6 changes: 2 additions & 4 deletions src/web/Jordnaer/Features/Chat/ChatSignalRClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
using Jordnaer.Shared;
using Jordnaer.SignalR;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.SignalR.Client;

namespace Jordnaer.Features.Chat;

public class ChatSignalRClient(
CurrentUser currentUser,
CookieContainerFactory cookieContainerFactory,
ILogger<AuthenticatedSignalRClientBase> logger,
IServer server,
NavigationManager navigationManager)
: AuthenticatedSignalRClientBase(currentUser, logger, server, navigationManager, "/hubs/chat")
: AuthenticatedSignalRClientBase(logger, cookieContainerFactory, navigationManager, "/hubs/chat")
{
public void OnMessageReceived(Func<SendMessage, Task> action)
{
Expand Down
6 changes: 2 additions & 4 deletions src/web/Jordnaer/Features/Chat/UnreadMessageSignalRClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
using Jordnaer.Shared;
using Jordnaer.SignalR;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.SignalR.Client;

namespace Jordnaer.Features.Chat;

public class UnreadMessageSignalRClient(
CurrentUser currentUser,
CookieContainerFactory cookieContainerFactory,
ILogger<AuthenticatedSignalRClientBase> logger,
IServer server,
NavigationManager navigationManager)
: AuthenticatedSignalRClientBase(currentUser, logger, server, navigationManager, "/hubs/chat")
: AuthenticatedSignalRClientBase(logger, cookieContainerFactory, navigationManager, "/hubs/chat")
{
public void OnMessageReceived(Func<SendMessage, Task> action)
{
Expand Down
66 changes: 3 additions & 63 deletions src/web/Jordnaer/SignalR/AuthenticatedSignalRClientBase.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,22 @@
using Jordnaer.Features.Authentication;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.SignalR.Client;
using System.Net;

namespace Jordnaer.SignalR;

public abstract class AuthenticatedSignalRClientBase : ISignalRClient
{
private readonly ILogger<AuthenticatedSignalRClientBase> _logger;
private readonly IServer _server;

protected AuthenticatedSignalRClientBase(CurrentUser currentUser,
protected AuthenticatedSignalRClientBase(
ILogger<AuthenticatedSignalRClientBase> logger,
IServer server,
CookieContainerFactory cookieContainerFactory,
NavigationManager navigationManager,
string hubPath)
{
_logger = logger;
_server = server;

if (currentUser.Id is null)
{
logger.LogDebug("CurrentUser is not logged in, cannot create an authenticated SignalR Connection.");
return;
}

if (currentUser.Cookie is null)
{
logger.LogWarning("CurrentUser {UserId} does not have a cookie, cannot create an authenticated SignalR Connection.", currentUser.Id);
return;
}

var cookieContainer = CreateCookieContainer(currentUser.Cookie);
var cookieContainer = cookieContainerFactory.Create();
if (cookieContainer is null)
{
return;
Expand Down Expand Up @@ -72,49 +55,6 @@ public async Task StopAsync(CancellationToken cancellationToken = default)
Started = false;
_logger.LogDebug("SignalR Client stopped");
}
}

private CookieContainer? CreateCookieContainer(string cookie)
{
var allServerUris = _server.Features.Get<IServerAddressesFeature>()?.Addresses;
_logger.LogDebug("All server addresses: {@ServerAddresses}", allServerUris);

var serverUri = _server.Features.Get<IServerAddressesFeature>()?.Addresses.FirstOrDefault();
if (serverUri is null)
{
_logger.LogError("Failed to get server address from IServer");
return null;
}

if (!serverUri.Contains("[::]"))
{
var cookieContainer = new CookieContainer(1);
cookieContainer.Add(new Cookie(
name: AuthenticationConstants.CookieName,
value: cookie,
path: "/",
domain: new Uri(serverUri).Host));
return cookieContainer;
}

_logger.LogInformation(
"First server address was {ServerUri}, trying to get hostname from environment variable 'WEBSITE_HOSTNAME' instead.", serverUri);

var domain = Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME");
if (domain is null)
{
_logger.LogError("Cannot determine domain for Cookie, " +
"environment variable 'WEBSITE_HOSTNAME' was null.");

return null;
}

var container = new CookieContainer(1);
container.Add(new Cookie(name: AuthenticationConstants.CookieName,
value: cookie,
path: "/",
domain: domain));
return container;
}

public async ValueTask DisposeAsync()
Expand Down

0 comments on commit 2b94993

Please sign in to comment.