Skip to content

Commit ca043ce

Browse files
committed
refactor: make statestorage non-generic
1 parent 0536123 commit ca043ce

File tree

18 files changed

+139
-185
lines changed

18 files changed

+139
-185
lines changed

src/ActiveLogin.Authentication.BankId.AspNetCore/Areas/ActiveLogin/Controllers/BankIdUiAuthController.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,13 @@ public class BankIdUiAuthController(
2222
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
2323
IBankIdUiOptionsProtector uiOptionsProtector,
2424
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
25-
IStateStorage<BankIdUiAuthState> stateStorage
26-
) : BankIdUiControllerBase<BankIdUiAuthState>(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler)
25+
IStateStorage stateStorage
26+
) : BankIdUiControllerBase<BankIdUiAuthState>(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler, stateStorage)
2727
{
2828
[HttpGet]
2929
[Route($"/[area]/{BankIdConstants.Routes.BankIdPathName}/{BankIdConstants.Routes.BankIdAuthControllerPath}")]
3030
public Task<ActionResult> Init(string returnUrl, [FromQuery(Name = BankIdConstants.QueryStringParameters.UiOptions)] string protectedUiOptions)
3131
{
3232
return Initialize(returnUrl, BankIdConstants.Routes.BankIdAuthApiControllerName, protectedUiOptions, "Init");
3333
}
34-
35-
protected override Task<BankIdUiAuthState?> GetUIState(BankIdUiOptions uiOptions)
36-
{
37-
var cookie = HttpContext.Request.Cookies[uiOptions.StateKeyCookieName];
38-
if (cookie is null)
39-
{
40-
return Task.FromResult<BankIdUiAuthState?>(null);
41-
}
42-
var stateKey = new StateKey(cookie);
43-
return stateStorage.RemoveAsync(stateKey);
44-
}
4534
}

src/ActiveLogin.Authentication.BankId.AspNetCore/Areas/ActiveLogin/Controllers/BankIdUiControllerBase.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ public abstract class BankIdUiControllerBase<T>(
2020
IStringLocalizer<ActiveLoginResources> localizer,
2121
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
2222
IBankIdUiOptionsProtector uiOptionsProtector,
23-
IBankIdInvalidStateHandler bankIdInvalidStateHandler
23+
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
24+
IStateStorage stateStorage
2425
) : Controller
2526
where T : BankIdUiState
2627
{
@@ -30,7 +31,16 @@ IBankIdInvalidStateHandler bankIdInvalidStateHandler
3031
private readonly IBankIdUiOptionsProtector _uiOptionsProtector = uiOptionsProtector;
3132
private readonly IBankIdInvalidStateHandler _bankIdInvalidStateHandler = bankIdInvalidStateHandler;
3233

33-
protected abstract Task<T?> GetUIState(BankIdUiOptions uiOptions);
34+
protected async Task<T?> GetUIState(BankIdUiOptions uiOptions)
35+
{
36+
var cookie = HttpContext.Request.Cookies[uiOptions.StateKeyCookieName];
37+
if (cookie is null)
38+
{
39+
return default;
40+
}
41+
var stateKey = new StateKey(cookie);
42+
return await stateStorage.ReadAsync(stateKey) as T;
43+
}
3444

3545
protected async Task<ActionResult> Initialize(string returnUrl, string apiControllerName, string protectedUiOptions, string viewName)
3646
{

src/ActiveLogin.Authentication.BankId.AspNetCore/Areas/ActiveLogin/Controllers/BankIdUiSignApiController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class BankIdUiSignApiController(
2828
IBankIdUserMessage bankIdUserMessage,
2929
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
3030
IBankIdUiResultProtector uiAuthResultProtector,
31-
IStateStorage<BankIdUiSignState> stateStorage
31+
IStateStorage stateStorage
3232
) : BankIdUiApiControllerBase(bankIdFlowService, orderRefProtector, qrStartStateProtector, uiOptionsProtector, bankIdUserMessage, bankIdUserMessageLocalizer, uiAuthResultProtector)
3333
{
3434
[ValidateAntiForgeryToken]
@@ -106,6 +106,6 @@ public async Task<ActionResult<BankIdUiApiInitializeResponse>> Initialize(BankId
106106
}
107107

108108
var stateKey = new StateKey(cookie);
109-
return stateStorage.ReadAsync(stateKey);
109+
return stateStorage.ReadAsync<BankIdUiSignState>(stateKey);
110110
}
111111
}

src/ActiveLogin.Authentication.BankId.AspNetCore/Areas/ActiveLogin/Controllers/BankIdUiSignController.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public class BankIdUiSignController(
2323
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
2424
IBankIdUiOptionsProtector uiOptionsProtector,
2525
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
26-
IStateStorage<BankIdUiSignState> stateStorage
27-
) : BankIdUiControllerBase<BankIdUiSignState>(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler)
26+
IStateStorage stateStorage
27+
) : BankIdUiControllerBase<BankIdUiSignState>(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler, stateStorage)
2828
{
2929
[HttpGet]
3030
[AllowAnonymous]
@@ -33,15 +33,4 @@ public Task<ActionResult> Init(string returnUrl, [FromQuery(Name = BankIdConstan
3333
{
3434
return Initialize(returnUrl, BankIdConstants.Routes.BankIdSignApiControllerName, protectedUiOptions, "Init");
3535
}
36-
37-
protected override Task<BankIdUiSignState?> GetUIState(BankIdUiOptions uiOptions)
38-
{
39-
var cookie = HttpContext.Request.Cookies[uiOptions.StateKeyCookieName];
40-
if (cookie is null)
41-
{
42-
return Task.FromResult<BankIdUiSignState?>(null);
43-
}
44-
var stateKey = new StateKey(cookie);
45-
return stateStorage.RemoveAsync(stateKey);
46-
}
4736
}

src/ActiveLogin.Authentication.BankId.AspNetCore/Auth/AuthenticationBuilderBankIdExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ private static void AddBankIdAuthDefaultServices(IBankIdAuthBuilder builder)
7474
BankIdCommonConfiguration.AddDefaultServices(services);
7575

7676
// services.AddTransient<IBankIdUiStateProtector, BankIdUiStateProtector>();
77-
services.AddSingleton<IStateStorage<BankIdUiAuthState>, InMemoryStateStorage<BankIdUiAuthState>>();
77+
services.AddSingleton<IStateStorage, InMemoryStateStorage>();
7878
services.AddTransient<IBankIdUiResultProtector, BankIdUiResultProtector>();
7979

8080
builder.AddClaimsTransformer<BankIdDefaultClaimsTransformer>();

src/ActiveLogin.Authentication.BankId.AspNetCore/Auth/BankIdAuthHandler.cs

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System.Security.Claims;
22
using System.Text.Encodings.Web;
33

4-
using ActiveLogin.Authentication.BankId.Api.Models;
54
using ActiveLogin.Authentication.BankId.AspNetCore.ClaimsTransformation;
65
using ActiveLogin.Authentication.BankId.AspNetCore.DataProtection;
76
using ActiveLogin.Authentication.BankId.AspNetCore.Helpers;
@@ -33,49 +32,40 @@ public class BankIdAuthHandler(
3332
IBankIdEventTrigger bankIdEventTrigger,
3433
IBankIdSupportedDeviceDetector bankIdSupportedDeviceDetector,
3534
IEnumerable<IBankIdClaimsTransformer> bankIdClaimsTransformers,
36-
IStateStorage<BankIdUiAuthState> stateStorage
35+
IStateStorage stateStorage
3736
) : RemoteAuthenticationHandler<BankIdAuthOptions>(options, loggerFactory, encoder)
3837
{
39-
private const string StateCookieNameParameterName = "StateCookie.Name";
4038
private readonly PathString _authPath = new($"/{BankIdConstants.Routes.ActiveLoginAreaName}/{BankIdConstants.Routes.BankIdPathName}/{BankIdConstants.Routes.BankIdAuthControllerPath}");
41-
42-
private readonly IHttpContextAccessor _httpContextAccessor = httpContextAccessor;
43-
private readonly IAntiforgery _antiforgery = antiforgery;
44-
private readonly IBankIdUiOptionsProtector _uiOptionsProtector = uiOptionsProtector;
45-
private readonly IBankIdUiResultProtector _uiResultProtector = uiResultProtector;
46-
private readonly IBankIdEventTrigger _bankIdEventTrigger = bankIdEventTrigger;
47-
private readonly IBankIdSupportedDeviceDetector _bankIdSupportedDeviceDetector = bankIdSupportedDeviceDetector;
48-
private readonly IStateStorage<BankIdUiAuthState> _stateStorage = stateStorage;
49-
private readonly List<IBankIdClaimsTransformer> _bankIdClaimsTransformers = bankIdClaimsTransformers.ToList();
39+
private readonly List<IBankIdClaimsTransformer> bankIdClaimsTransformers = bankIdClaimsTransformers.ToList();
5040

5141
protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
5242
{
53-
var detectedDevice = _bankIdSupportedDeviceDetector.Detect();
43+
var detectedDevice = bankIdSupportedDeviceDetector.Detect();
5444

5545
var state = await GetStateFromCookie();
5646
if (state == null)
5747
{
5848
return await HandleRemoteAuthenticateFail(BankIdConstants.ErrorMessages.InvalidStateCookie, detectedDevice);
5949
}
6050

61-
DeleteStateCookie();
51+
await DeleteStateCookie();
6252

6353
if (!Request.HasFormContentType)
6454
{
6555
await HandleRemoteAuthenticateFail(BankIdConstants.ErrorMessages.InvalidUiResult, detectedDevice);
6656
throw new ArgumentException(BankIdConstants.ErrorMessages.InvalidUiResult);
6757
}
6858

69-
var httpContext = _httpContextAccessor.HttpContext ?? throw new InvalidOperationException(BankIdConstants.ErrorMessages.CouldNotAccessHttpContext);
70-
await _antiforgery.ValidateRequestAsync(httpContext);
59+
var httpContext = httpContextAccessor.HttpContext ?? throw new InvalidOperationException(BankIdConstants.ErrorMessages.CouldNotAccessHttpContext);
60+
await antiforgery.ValidateRequestAsync(httpContext);
7161

7262
var protectedUiResult = Request.Form[BankIdConstants.FormParameters.UiResult];
7363
if (StringValues.IsNullOrEmpty(protectedUiResult))
7464
{
7565
return await HandleRemoteAuthenticateFail(BankIdConstants.ErrorMessages.InvalidUiResult, detectedDevice);
7666
}
7767

78-
var uiResult = _uiResultProtector.Unprotect(protectedUiResult.ToString());
68+
var uiResult = uiResultProtector.Unprotect(protectedUiResult.ToString());
7969
if (!uiResult.IsSuccessful)
8070
{
8171
return await HandleRemoteAuthenticateFail(BankIdConstants.ErrorMessages.InvalidUiResult, detectedDevice);
@@ -84,7 +74,7 @@ protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync
8474
var properties = state.AuthenticationProperties;
8575
var ticket = await GetAuthenticationTicket(uiResult, properties);
8676

87-
await _bankIdEventTrigger.TriggerAsync(new BankIdAspNetAuthenticateSuccessEvent(
77+
await bankIdEventTrigger.TriggerAsync(new BankIdAspNetAuthenticateSuccessEvent(
8878
PersonalIdentityNumber.Parse(uiResult.PersonalIdentityNumber),
8979
detectedDevice
9080
));
@@ -94,7 +84,7 @@ await _bankIdEventTrigger.TriggerAsync(new BankIdAspNetAuthenticateSuccessEvent(
9484

9585
private async Task<HandleRequestResult> HandleRemoteAuthenticateFail(string reason, BankIdSupportedDevice detectedDevice)
9686
{
97-
await _bankIdEventTrigger.TriggerAsync(new BankIdAspNetAuthenticateFailureEvent(reason, detectedDevice));
87+
await bankIdEventTrigger.TriggerAsync(new BankIdAspNetAuthenticateFailureEvent(reason, detectedDevice));
9888

9989
return HandleRequestResult.Fail(reason);
10090
}
@@ -134,7 +124,7 @@ private async Task<IEnumerable<Claim>> GetClaims(BankIdUiResult uiAuthResult)
134124
uiAuthResult.GetCompletionData()
135125
);
136126

137-
foreach (var transformer in _bankIdClaimsTransformers)
127+
foreach (var transformer in bankIdClaimsTransformers)
138128
{
139129
await transformer.TransformClaims(context);
140130
}
@@ -157,8 +147,8 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop
157147
Options.StateCookie.Name ?? string.Empty
158148
);
159149

160-
var detectedDevice = _bankIdSupportedDeviceDetector.Detect();
161-
await _bankIdEventTrigger.TriggerAsync(new BankIdAspNetChallengeSuccessEvent(detectedDevice, uiOptions.ToBankIdFlowOptions()));
150+
var detectedDevice = bankIdSupportedDeviceDetector.Detect();
151+
await bankIdEventTrigger.TriggerAsync(new BankIdAspNetChallengeSuccessEvent(detectedDevice, uiOptions.ToBankIdFlowOptions()));
162152

163153
var loginUrl = GetInitUiUrl(uiOptions);
164154
Response.Redirect(loginUrl);
@@ -169,7 +159,7 @@ private string GetInitUiUrl(BankIdUiOptions uiOptions)
169159
var pathBase = Context.Request.PathBase;
170160
var authUrl = pathBase.Add(_authPath);
171161
var returnUrl = pathBase.Add(Options.CallbackPath);
172-
var protectedUiOptions = _uiOptionsProtector.Protect(uiOptions);
162+
var protectedUiOptions = uiOptionsProtector.Protect(uiOptions);
173163

174164
var queryBuilder = new QueryBuilder(new Dictionary<string, string>
175165
{
@@ -182,42 +172,45 @@ private string GetInitUiUrl(BankIdUiOptions uiOptions)
182172

183173
private async Task AppendStateCookie(AuthenticationProperties properties)
184174
{
185-
Validators.ThrowIfNullOrWhitespace(Options.StateCookie.Name, StateCookieNameParameterName);
175+
Validators.ThrowIfNullOrWhitespace(Options.StateCookie.Name, BankIdConstants.AuthStateKey);
186176

187177
if (Options.TimeProvider == null)
188178
{
189179
throw new InvalidOperationException(BankIdConstants.ErrorMessages.TimeProviderNotSet);
190180
}
191181

192182
var state = new BankIdUiAuthState(properties);
193-
var stateKey = await _stateStorage.WriteAsync(state);
183+
var stateKey = await stateStorage.WriteAsync(state);
194184

195185
var cookieOptions = Options.StateCookie.Build(Context, Options.TimeProvider.GetUtcNow());
196186
Response.Cookies.Append(Options.StateCookie.Name, stateKey, cookieOptions);
197187
}
198188

199189
private Task<BankIdUiAuthState?> GetStateFromCookie()
200190
{
201-
Validators.ThrowIfNullOrWhitespace(Options.StateCookie.Name, StateCookieNameParameterName);
191+
Validators.ThrowIfNullOrWhitespace(Options.StateCookie.Name, BankIdConstants.AuthStateKey);
202192

203193
var stateKey = Request.Cookies[Options.StateCookie.Name];
204194
if (string.IsNullOrEmpty(stateKey))
205195
{
206196
return Task.FromResult<BankIdUiAuthState?>(null);
207197
}
208198

209-
return _stateStorage.ReadAsync(new(stateKey));
199+
return stateStorage.ReadAsync<BankIdUiAuthState>(new(stateKey));
210200
}
211201

212-
private void DeleteStateCookie()
202+
private async Task DeleteStateCookie()
213203
{
214-
Validators.ThrowIfNullOrWhitespace(Options.StateCookie.Name, StateCookieNameParameterName);
204+
Validators.ThrowIfNullOrWhitespace(Options.StateCookie.Name, BankIdConstants.AuthStateKey);
215205

216206
if (Options.TimeProvider == null)
217207
{
218208
throw new InvalidOperationException(BankIdConstants.ErrorMessages.TimeProviderNotSet);
219209
}
220210

211+
var stateKey = Request.Cookies[Options.StateCookie.Name]!;
212+
_ = await stateStorage.RemoveAsync(new(stateKey));
213+
221214
var cookieOptions = Options.StateCookie.Build(Context, Options.TimeProvider.GetUtcNow());
222215
Response.Cookies.Delete(Options.StateCookie.Name, cookieOptions);
223216
}

src/ActiveLogin.Authentication.BankId.AspNetCore/Auth/IBankIdAuthBuilderExtensions.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using ActiveLogin.Authentication.BankId.AspNetCore.ClaimsTransformation;
2+
using ActiveLogin.Authentication.BankId.Core;
23
using ActiveLogin.Authentication.BankId.Core.Requirements;
34
using ActiveLogin.Authentication.BankId.Core.UserData;
45

@@ -182,4 +183,24 @@ internal static IBankIdAuthBuilder AddScheme(this IBankIdAuthBuilder builder, st
182183

183184
return builder;
184185
}
186+
187+
public static IBankIdAuthBuilder AddStateStorage<T>(this IBankIdAuthBuilder builder, T storage)
188+
where T : class, IStateStorage
189+
{
190+
builder.Services.AddSingleton(storage);
191+
return builder;
192+
}
193+
194+
public static IBankIdAuthBuilder AddStateStorage<T>(this IBankIdAuthBuilder builder)
195+
where T : class, IStateStorage
196+
{
197+
builder.Services.AddSingleton<IStateStorage, T>();
198+
return builder;
199+
}
200+
201+
public static IBankIdAuthBuilder AddStateStorage(this IBankIdAuthBuilder builder, Func<IServiceProvider, IStateStorage> factory)
202+
{
203+
builder.Services.AddSingleton(factory);
204+
return builder;
205+
}
185206
}

src/ActiveLogin.Authentication.BankId.AspNetCore/DataProtection/BankIdUiStateProtector.cs

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/ActiveLogin.Authentication.BankId.AspNetCore/DataProtection/IBankIdUiStateProtector.cs

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)