Skip to content

Commit 0536123

Browse files
committed
feat(#478): replace cookie with storage
1 parent e6d16d3 commit 0536123

21 files changed

Lines changed: 404 additions & 382 deletions
Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
using ActiveLogin.Authentication.BankId.AspNetCore.Auth;
12
using ActiveLogin.Authentication.BankId.AspNetCore.DataProtection;
3+
using ActiveLogin.Authentication.BankId.AspNetCore.Models;
24
using ActiveLogin.Authentication.BankId.AspNetCore.StateHandling;
5+
using ActiveLogin.Authentication.BankId.Core;
36
using ActiveLogin.Authentication.BankId.Core.UserMessage;
47

58
using Microsoft.AspNetCore.Antiforgery;
69
using Microsoft.AspNetCore.Authorization;
10+
using Microsoft.AspNetCore.Http;
711
using Microsoft.AspNetCore.Mvc;
812
using Microsoft.Extensions.Localization;
913

@@ -12,25 +16,30 @@ namespace ActiveLogin.Authentication.BankId.AspNetCore.Areas.ActiveLogin.Control
1216
[Area(BankIdConstants.Routes.ActiveLoginAreaName)]
1317
[AllowAnonymous]
1418
[NonController]
15-
public class BankIdUiAuthController : BankIdUiControllerBase
19+
public class BankIdUiAuthController(
20+
IAntiforgery antiforgery,
21+
IStringLocalizer<ActiveLoginResources> localizer,
22+
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
23+
IBankIdUiOptionsProtector uiOptionsProtector,
24+
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
25+
IStateStorage<BankIdUiAuthState> stateStorage
26+
) : BankIdUiControllerBase<BankIdUiAuthState>(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler)
1627
{
17-
public BankIdUiAuthController(
18-
IAntiforgery antiforgery,
19-
IStringLocalizer<ActiveLoginResources> localizer,
20-
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
21-
IBankIdUiOptionsProtector uiOptionsProtector,
22-
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
23-
IBankIdUiStateProtector bankIdUiStateProtector
24-
)
25-
: base(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler, bankIdUiStateProtector)
26-
{
27-
28-
}
29-
3028
[HttpGet]
3129
[Route($"/[area]/{BankIdConstants.Routes.BankIdPathName}/{BankIdConstants.Routes.BankIdAuthControllerPath}")]
3230
public Task<ActionResult> Init(string returnUrl, [FromQuery(Name = BankIdConstants.QueryStringParameters.UiOptions)] string protectedUiOptions)
3331
{
3432
return Initialize(returnUrl, BankIdConstants.Routes.BankIdAuthApiControllerName, protectedUiOptions, "Init");
3533
}
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+
}
3645
}

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

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using ActiveLogin.Authentication.BankId.AspNetCore.Models;
66
using ActiveLogin.Authentication.BankId.AspNetCore.Sign;
77
using ActiveLogin.Authentication.BankId.AspNetCore.StateHandling;
8+
using ActiveLogin.Authentication.BankId.Core;
89
using ActiveLogin.Authentication.BankId.Core.UserMessage;
910

1011
using Microsoft.AspNetCore.Antiforgery;
@@ -14,30 +15,22 @@
1415
namespace ActiveLogin.Authentication.BankId.AspNetCore.Areas.ActiveLogin.Controllers;
1516

1617
[NonController]
17-
public abstract class BankIdUiControllerBase : Controller
18+
public abstract class BankIdUiControllerBase<T>(
19+
IAntiforgery antiforgery,
20+
IStringLocalizer<ActiveLoginResources> localizer,
21+
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
22+
IBankIdUiOptionsProtector uiOptionsProtector,
23+
IBankIdInvalidStateHandler bankIdInvalidStateHandler
24+
) : Controller
25+
where T : BankIdUiState
1826
{
19-
private readonly IAntiforgery _antiforgery;
20-
private readonly IStringLocalizer<ActiveLoginResources> _localizer;
21-
private readonly IBankIdUserMessageLocalizer _bankIdUserMessageLocalizer;
22-
private readonly IBankIdUiOptionsProtector _uiOptionsProtector;
23-
private readonly IBankIdInvalidStateHandler _bankIdInvalidStateHandler;
24-
private readonly IBankIdUiStateProtector _bankIdUiStateProtector;
25-
26-
protected BankIdUiControllerBase(
27-
IAntiforgery antiforgery,
28-
IStringLocalizer<ActiveLoginResources> localizer,
29-
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
30-
IBankIdUiOptionsProtector uiOptionsProtector,
31-
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
32-
IBankIdUiStateProtector bankIdUiStateProtector)
33-
{
34-
_antiforgery = antiforgery;
35-
_localizer = localizer;
36-
_bankIdUserMessageLocalizer = bankIdUserMessageLocalizer;
37-
_uiOptionsProtector = uiOptionsProtector;
38-
_bankIdInvalidStateHandler = bankIdInvalidStateHandler;
39-
_bankIdUiStateProtector = bankIdUiStateProtector;
40-
}
27+
private readonly IAntiforgery _antiforgery = antiforgery;
28+
private readonly IStringLocalizer<ActiveLoginResources> _localizer = localizer;
29+
private readonly IBankIdUserMessageLocalizer _bankIdUserMessageLocalizer = bankIdUserMessageLocalizer;
30+
private readonly IBankIdUiOptionsProtector _uiOptionsProtector = uiOptionsProtector;
31+
private readonly IBankIdInvalidStateHandler _bankIdInvalidStateHandler = bankIdInvalidStateHandler;
32+
33+
protected abstract Task<T?> GetUIState(BankIdUiOptions uiOptions);
4134

4235
protected async Task<ActionResult> Initialize(string returnUrl, string apiControllerName, string protectedUiOptions, string viewName)
4336
{
@@ -58,32 +51,40 @@ protected async Task<ActionResult> Initialize(string returnUrl, string apiContro
5851
return new EmptyResult();
5952
}
6053

61-
var antiforgeryTokens = _antiforgery.GetAndStoreTokens(HttpContext);
54+
var state = await GetUIState(uiOptions);
6255

63-
var protectedState = Request.Cookies[uiOptions.StateCookieName];
64-
if(protectedState == null)
56+
if (state == null)
6557
{
6658
var invalidStateContext = new BankIdInvalidStateContext(uiOptions.CancelReturnUrl);
6759
await _bankIdInvalidStateHandler.HandleAsync(invalidStateContext);
6860

6961
return new EmptyResult();
7062
}
71-
var state = _bankIdUiStateProtector.Unprotect(protectedState);
7263

64+
var antiforgeryTokens = _antiforgery.GetAndStoreTokens(HttpContext);
7365
var viewModel = GetUiViewModel(returnUrl, apiControllerName, protectedUiOptions, uiOptions, state, antiforgeryTokens);
7466

7567
return View(viewName, viewModel);
7668
}
7769

7870
private bool HasStateCookie(BankIdUiOptions uiOptions)
7971
{
80-
if (string.IsNullOrEmpty(uiOptions.StateCookieName)
81-
|| !HttpContext.Request.Cookies.ContainsKey(uiOptions.StateCookieName))
72+
if (string.IsNullOrEmpty(uiOptions.StateKeyCookieName))
73+
{
74+
return false;
75+
}
76+
77+
if (!HttpContext.Request.Cookies.ContainsKey(uiOptions.StateKeyCookieName))
78+
{
79+
return false;
80+
}
81+
82+
if (string.IsNullOrEmpty(HttpContext.Request.Cookies[uiOptions.StateKeyCookieName]))
8283
{
8384
return false;
8485
}
8586

86-
return !string.IsNullOrEmpty(HttpContext.Request.Cookies[uiOptions.StateCookieName]);
87+
return true;
8788
}
8889

8990
private BankIdUiViewModel GetUiViewModel(string returnUrl, string apiControllerName, string protectedUiOptions, BankIdUiOptions unprotectedUiOptions, BankIdUiState uiState, AntiforgeryTokenSet antiforgeryTokens)
@@ -122,7 +123,7 @@ private BankIdUiViewModel GetUiViewModel(string returnUrl, string apiControllerN
122123
var localizedCancelButtonText = _localizer["Cancel_Button"];
123124
var localizedQrCodeImageAltText = _localizer["Qr_Code_Image"];
124125

125-
if(uiState is BankIdUiSignState signState)
126+
if (uiState is BankIdUiSignState signState)
126127
{
127128
var uiSignData = new BankIdUiSignData
128129
{

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

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using ActiveLogin.Authentication.BankId.AspNetCore.Helpers;
66
using ActiveLogin.Authentication.BankId.AspNetCore.Models;
77
using ActiveLogin.Authentication.BankId.AspNetCore.Sign;
8+
using ActiveLogin.Authentication.BankId.Core;
89
using ActiveLogin.Authentication.BankId.Core.Flow;
910
using ActiveLogin.Authentication.BankId.Core.Models;
1011
using ActiveLogin.Authentication.BankId.Core.UserMessage;
@@ -19,24 +20,17 @@ namespace ActiveLogin.Authentication.BankId.AspNetCore.Areas.ActiveLogin.Control
1920
[ApiController]
2021
[AllowAnonymous]
2122
[NonController]
22-
public class BankIdUiSignApiController : BankIdUiApiControllerBase
23+
public class BankIdUiSignApiController(
24+
IBankIdFlowService bankIdFlowService,
25+
IBankIdUiOrderRefProtector orderRefProtector,
26+
IBankIdQrStartStateProtector qrStartStateProtector,
27+
IBankIdUiOptionsProtector uiOptionsProtector,
28+
IBankIdUserMessage bankIdUserMessage,
29+
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
30+
IBankIdUiResultProtector uiAuthResultProtector,
31+
IStateStorage<BankIdUiSignState> stateStorage
32+
) : BankIdUiApiControllerBase(bankIdFlowService, orderRefProtector, qrStartStateProtector, uiOptionsProtector, bankIdUserMessage, bankIdUserMessageLocalizer, uiAuthResultProtector)
2333
{
24-
private readonly IBankIdUiStateProtector _bankIdUiStateProtector;
25-
26-
public BankIdUiSignApiController(
27-
IBankIdFlowService bankIdFlowService,
28-
IBankIdUiOrderRefProtector orderRefProtector,
29-
IBankIdQrStartStateProtector qrStartStateProtector,
30-
IBankIdUiOptionsProtector uiOptionsProtector,
31-
IBankIdUserMessage bankIdUserMessage,
32-
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
33-
IBankIdUiResultProtector uiAuthResultProtector,
34-
IBankIdUiStateProtector bankIdUiStateProtector)
35-
: base(bankIdFlowService, orderRefProtector, qrStartStateProtector, uiOptionsProtector, bankIdUserMessage, bankIdUserMessageLocalizer, uiAuthResultProtector)
36-
{
37-
_bankIdUiStateProtector = bankIdUiStateProtector;
38-
}
39-
4034
[ValidateAntiForgeryToken]
4135
[HttpPost(BankIdConstants.Routes.BankIdApiInitializeActionName)]
4236
public async Task<ActionResult<BankIdUiApiInitializeResponse>> Initialize(BankIdUiApiInitializeRequest request)
@@ -46,8 +40,8 @@ public async Task<ActionResult<BankIdUiApiInitializeResponse>> Initialize(BankId
4640

4741
var uiOptions = UiOptionsProtector.Unprotect(request.UiOptions);
4842

49-
var state = GetStateFromCookie(uiOptions);
50-
if(state == null)
43+
var state = await GetState(uiOptions);
44+
if (state == null)
5145
{
5246
throw new InvalidOperationException(BankIdConstants.ErrorMessages.InvalidStateCookie);
5347
}
@@ -103,14 +97,15 @@ public async Task<ActionResult<BankIdUiApiInitializeResponse>> Initialize(BankId
10397
}
10498
}
10599

106-
private BankIdUiSignState? GetStateFromCookie(BankIdUiOptions uiOptions)
100+
private Task<BankIdUiSignState?> GetState(BankIdUiOptions uiOptions)
107101
{
108-
var protectedState = Request.Cookies[uiOptions.StateCookieName];
109-
if (protectedState == null)
102+
var cookie = Request.Cookies[uiOptions.StateKeyCookieName];
103+
if (cookie == null)
110104
{
111-
throw new InvalidOperationException(BankIdConstants.ErrorMessages.InvalidStateCookie);
105+
return Task.FromResult<BankIdUiSignState?>(null);
112106
}
113107

114-
return _bankIdUiStateProtector.Unprotect(protectedState) as BankIdUiSignState;
108+
var stateKey = new StateKey(cookie);
109+
return stateStorage.ReadAsync(stateKey);
115110
}
116111
}
Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
using ActiveLogin.Authentication.BankId.AspNetCore.Areas.ActiveLogin.Models;
12
using ActiveLogin.Authentication.BankId.AspNetCore.DataProtection;
3+
using ActiveLogin.Authentication.BankId.AspNetCore.Models;
4+
using ActiveLogin.Authentication.BankId.AspNetCore.Sign;
25
using ActiveLogin.Authentication.BankId.AspNetCore.StateHandling;
6+
using ActiveLogin.Authentication.BankId.Core;
37
using ActiveLogin.Authentication.BankId.Core.UserMessage;
48

59
using Microsoft.AspNetCore.Antiforgery;
610
using Microsoft.AspNetCore.Authorization;
11+
using Microsoft.AspNetCore.Http;
712
using Microsoft.AspNetCore.Mvc;
813
using Microsoft.Extensions.Localization;
914

@@ -12,26 +17,31 @@ namespace ActiveLogin.Authentication.BankId.AspNetCore.Areas.ActiveLogin.Control
1217
[Area(BankIdConstants.Routes.ActiveLoginAreaName)]
1318
[AllowAnonymous]
1419
[NonController]
15-
public class BankIdUiSignController : BankIdUiControllerBase
20+
public class BankIdUiSignController(
21+
IAntiforgery antiforgery,
22+
IStringLocalizer<ActiveLoginResources> localizer,
23+
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
24+
IBankIdUiOptionsProtector uiOptionsProtector,
25+
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
26+
IStateStorage<BankIdUiSignState> stateStorage
27+
) : BankIdUiControllerBase<BankIdUiSignState>(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler)
1628
{
17-
public BankIdUiSignController(
18-
IAntiforgery antiforgery,
19-
IStringLocalizer<ActiveLoginResources> localizer,
20-
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
21-
IBankIdUiOptionsProtector uiOptionsProtector,
22-
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
23-
IBankIdUiStateProtector bankIdUiStateProtector
24-
)
25-
: base(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler, bankIdUiStateProtector)
26-
{
27-
28-
}
29-
3029
[HttpGet]
3130
[AllowAnonymous]
3231
[Route($"/[area]/{BankIdConstants.Routes.BankIdPathName}/{BankIdConstants.Routes.BankIdSignControllerPath}")]
3332
public Task<ActionResult> Init(string returnUrl, [FromQuery(Name = BankIdConstants.QueryStringParameters.UiOptions)] string protectedUiOptions)
3433
{
3534
return Initialize(returnUrl, BankIdConstants.Routes.BankIdSignApiControllerName, protectedUiOptions, "Init");
3635
}
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+
}
3747
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using ActiveLogin.Authentication.BankId.AspNetCore.ApplicationFeatureProviders;
22
using ActiveLogin.Authentication.BankId.AspNetCore.ClaimsTransformation;
33
using ActiveLogin.Authentication.BankId.AspNetCore.DataProtection;
4+
using ActiveLogin.Authentication.BankId.AspNetCore.Sign;
45
using ActiveLogin.Authentication.BankId.Core;
56
using ActiveLogin.Authentication.BankId.Core.Requirements;
67
using ActiveLogin.Authentication.BankId.Core.UserData;
@@ -72,7 +73,8 @@ private static void AddBankIdAuthDefaultServices(IBankIdAuthBuilder builder)
7273

7374
BankIdCommonConfiguration.AddDefaultServices(services);
7475

75-
services.AddTransient<IBankIdUiStateProtector, BankIdUiStateProtector>();
76+
// services.AddTransient<IBankIdUiStateProtector, BankIdUiStateProtector>();
77+
services.AddSingleton<IStateStorage<BankIdUiAuthState>, InMemoryStateStorage<BankIdUiAuthState>>();
7678
services.AddTransient<IBankIdUiResultProtector, BankIdUiResultProtector>();
7779

7880
builder.AddClaimsTransformer<BankIdDefaultClaimsTransformer>();

0 commit comments

Comments
 (0)