Skip to content

Commit

Permalink
Rename to 'AuthenticationContext', make IAuthenticationContext more r…
Browse files Browse the repository at this point in the history
…obust
  • Loading branch information
martinothamar committed Nov 8, 2024
1 parent 24d3b60 commit 9a48939
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ IWebHostEnvironment env
services.TryAddTransient<IApplicationLanguage, Internal.Language.ApplicationLanguage>();
services.TryAddTransient<IAuthorizationService, AuthorizationService>();

services.AddClientContext();
services.AddAuthenticationContext();
}

private static void AddApplicationIdentifier(IServiceCollection services)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class AuthenticationClient : IAuthenticationClient
{
private readonly ILogger _logger;
private readonly HttpClient _client;
private readonly IClientContext _clientContext;
private readonly IAuthenticationContext _authenticationContext;

/// <summary>
/// Initializes a new instance of the <see cref="AuthenticationClient"/> class
Expand All @@ -37,14 +37,14 @@ IServiceProvider serviceProvider
httpClient.DefaultRequestHeaders.Add(General.SubscriptionKeyHeaderName, platformSettings.Value.SubscriptionKey);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client = httpClient;
_clientContext = serviceProvider.GetRequiredService<IClientContext>();
_authenticationContext = serviceProvider.GetRequiredService<IAuthenticationContext>();
}

/// <inheritdoc />
public async Task<string> RefreshToken()
{
string endpointUrl = $"refresh";
string token = _clientContext.Current.Token; // TODO: check if authenticated?
string token = _authenticationContext.Current.Token; // TODO: check if authenticated?

Check warning on line 47 in src/Altinn.App.Core/Infrastructure/Clients/Authentication/AuthenticationClient.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)
HttpResponseMessage response = await _client.GetAsync(token, endpointUrl);

if (response.StatusCode == System.Net.HttpStatusCode.OK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,32 @@

namespace Altinn.App.Core.Internal.Auth;

internal static class ClientContextDI
internal static class AuthenticationContextDI
{
internal static void AddClientContext(this IServiceCollection services)
internal static void AddAuthenticationContext(this IServiceCollection services)
{
services.TryAddSingleton<IClientContext, ClientContext>();
services.TryAddSingleton<IAuthenticationContext, AuthenticationContext>();
}
}

internal abstract record ClientContextData(string Token)
internal abstract record AuthenticationInfo
{
internal sealed record Unauthenticated(string Token) : ClientContextData(Token);
public string Token { get; }

internal sealed record User(int UserId, int PartyId, string Token) : ClientContextData(Token);
private AuthenticationInfo(string token) => Token = token;

internal sealed record Org(string OrgName, string OrgNo, int PartyId, string Token) : ClientContextData(Token);
internal sealed record Unauthenticated(string Token) : AuthenticationInfo(Token);

internal sealed record User(int UserId, int PartyId, string Token) : AuthenticationInfo(Token);

internal sealed record Org(string OrgName, string OrgNo, int PartyId, string Token) : AuthenticationInfo(Token);

internal sealed record SystemUser(IReadOnlyList<string> SystemUserId, string SystemId, string Token)
: ClientContextData(Token);
: AuthenticationInfo(Token);

// internal sealed record App(string Token) : ClientContextData;

Check warning on line 37 in src/Altinn.App.Core/Internal/Auth/IAuthenticationContext.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

internal static ClientContextData From(HttpContext httpContext, string cookieName)
internal static AuthenticationInfo From(HttpContext httpContext, string cookieName)

Check warning on line 39 in src/Altinn.App.Core/Internal/Auth/IAuthenticationContext.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

Refactor this method to reduce its Cognitive Complexity from 21 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)
{
string token = JwtTokenUtil.GetTokenFromContext(httpContext, cookieName);
if (string.IsNullOrWhiteSpace(token))
Expand Down Expand Up @@ -114,25 +118,53 @@ private sealed record SystemUserAuthorizationDetailsClaim(
);
}

internal interface IClientContext
internal interface IAuthenticationContext
{
ClientContextData Current { get; }
AuthenticationInfo Current { get; }
}

internal sealed class ClientContext : IClientContext
internal sealed class AuthenticationContext : IAuthenticationContext
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IOptionsMonitor<AppSettings> _appSettings;

public ClientContext(IHttpContextAccessor httpContextAccessor, IOptionsMonitor<AppSettings> appSettings)
private readonly object _lck = new();

public AuthenticationContext(IHttpContextAccessor httpContextAccessor, IOptionsMonitor<AppSettings> appSettings)
{
_httpContextAccessor = httpContextAccessor;
_appSettings = appSettings;
}

public ClientContextData Current =>
ClientContextData.From(
_httpContextAccessor.HttpContext ?? throw new InvalidOperationException("No HTTP context available"),
_appSettings.CurrentValue.RuntimeCookieName
);
public AuthenticationInfo Current
{
get
{
// Currently we're coupling this to the HTTP context directly.
// In the future we might want to run work (e.g. service tasks) in the background,
// at which point we won't always have a HTTP context available.
// At that point we probably want to implement something like an `IExecutionContext`, `IExecutionContextAccessor`
// to decouple ourselves from the ASP.NET request context.
// TODO: consider removing dependcy on HTTP context

Check warning on line 148 in src/Altinn.App.Core/Internal/Auth/IAuthenticationContext.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)
var httpContext =
_httpContextAccessor.HttpContext ?? throw new InvalidOperationException("No HTTP context available");

lock (_lck)
{
const string key = "Internal_AltinnAuthenticationInfo";
if (httpContext.Items.TryGetValue(key, out var authInfoObj))
{
if (authInfoObj is not AuthenticationInfo authInfo)
throw new InvalidOperationException("Invalid authentication info object in HTTP context items");
return authInfo;
}
else
{
var authInfo = AuthenticationInfo.From(httpContext, _appSettings.CurrentValue.RuntimeCookieName);
httpContext.Items[key] = authInfo;
return authInfo;
}
}
}
}
}

0 comments on commit 9a48939

Please sign in to comment.