Skip to content

Commit 58c075e

Browse files
committed
feat(#478): replace cookie with storage
1 parent 74fe37d commit 58c075e

22 files changed

Lines changed: 376 additions & 261 deletions

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

Lines changed: 12 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,21 +16,15 @@ 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 stateStorage
26+
) : BankIdUiControllerBase<BankIdUiAuthState>(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler, stateStorage)
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)

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

Lines changed: 35 additions & 13 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,29 +15,42 @@
1415
namespace ActiveLogin.Authentication.BankId.AspNetCore.Areas.ActiveLogin.Controllers;
1516

1617
[NonController]
17-
public abstract class BankIdUiControllerBase : Controller
18+
public abstract class BankIdUiControllerBase<T> : Controller
19+
where T : BankIdUiState
1820
{
1921
private readonly IAntiforgery _antiforgery;
2022
private readonly IStringLocalizer<ActiveLoginResources> _localizer;
2123
private readonly IBankIdUserMessageLocalizer _bankIdUserMessageLocalizer;
2224
private readonly IBankIdUiOptionsProtector _uiOptionsProtector;
2325
private readonly IBankIdInvalidStateHandler _bankIdInvalidStateHandler;
24-
private readonly IBankIdUiStateProtector _bankIdUiStateProtector;
26+
private readonly IStateStorage stateStorage;
2527

26-
protected BankIdUiControllerBase(
28+
public BankIdUiControllerBase(
2729
IAntiforgery antiforgery,
2830
IStringLocalizer<ActiveLoginResources> localizer,
2931
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
3032
IBankIdUiOptionsProtector uiOptionsProtector,
3133
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
32-
IBankIdUiStateProtector bankIdUiStateProtector)
34+
IStateStorage stateStorage
35+
)
3336
{
37+
this.stateStorage = stateStorage;
3438
_antiforgery = antiforgery;
3539
_localizer = localizer;
3640
_bankIdUserMessageLocalizer = bankIdUserMessageLocalizer;
3741
_uiOptionsProtector = uiOptionsProtector;
3842
_bankIdInvalidStateHandler = bankIdInvalidStateHandler;
39-
_bankIdUiStateProtector = bankIdUiStateProtector;
43+
}
44+
45+
protected async Task<T?> GetUIState(BankIdUiOptions uiOptions)
46+
{
47+
var cookie = HttpContext.Request.Cookies[uiOptions.StateKeyCookieName];
48+
if (cookie is null)
49+
{
50+
return default;
51+
}
52+
var stateKey = new StateKey(cookie);
53+
return await stateStorage.ReadAsync(stateKey) as T;
4054
}
4155

4256
protected async Task<ActionResult> Initialize(string returnUrl, string apiControllerName, string protectedUiOptions, string viewName)
@@ -58,32 +72,40 @@ protected async Task<ActionResult> Initialize(string returnUrl, string apiContro
5872
return new EmptyResult();
5973
}
6074

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

63-
var protectedState = Request.Cookies[uiOptions.StateCookieName];
64-
if(protectedState == null)
77+
if (state == null)
6578
{
6679
var invalidStateContext = new BankIdInvalidStateContext(uiOptions.CancelReturnUrl);
6780
await _bankIdInvalidStateHandler.HandleAsync(invalidStateContext);
6881

6982
return new EmptyResult();
7083
}
71-
var state = _bankIdUiStateProtector.Unprotect(protectedState);
7284

85+
var antiforgeryTokens = _antiforgery.GetAndStoreTokens(HttpContext);
7386
var viewModel = GetUiViewModel(returnUrl, apiControllerName, protectedUiOptions, uiOptions, state, antiforgeryTokens);
7487

7588
return View(viewName, viewModel);
7689
}
7790

7891
private bool HasStateCookie(BankIdUiOptions uiOptions)
7992
{
80-
if (string.IsNullOrEmpty(uiOptions.StateCookieName)
81-
|| !HttpContext.Request.Cookies.ContainsKey(uiOptions.StateCookieName))
93+
if (string.IsNullOrEmpty(uiOptions.StateKeyCookieName))
94+
{
95+
return false;
96+
}
97+
98+
if (!HttpContext.Request.Cookies.ContainsKey(uiOptions.StateKeyCookieName))
99+
{
100+
return false;
101+
}
102+
103+
if (string.IsNullOrEmpty(HttpContext.Request.Cookies[uiOptions.StateKeyCookieName]))
82104
{
83105
return false;
84106
}
85107

86-
return !string.IsNullOrEmpty(HttpContext.Request.Cookies[uiOptions.StateCookieName]);
108+
return true;
87109
}
88110

89111
private BankIdUiViewModel GetUiViewModel(string returnUrl, string apiControllerName, string protectedUiOptions, BankIdUiOptions unprotectedUiOptions, BankIdUiState uiState, AntiforgeryTokenSet antiforgeryTokens)
@@ -122,7 +144,7 @@ private BankIdUiViewModel GetUiViewModel(string returnUrl, string apiControllerN
122144
var localizedCancelButtonText = _localizer["Cancel_Button"];
123145
var localizedQrCodeImageAltText = _localizer["Qr_Code_Image"];
124146

125-
if(uiState is BankIdUiSignState signState)
147+
if (uiState is BankIdUiSignState signState)
126148
{
127149
var uiSignData = new BankIdUiSignData
128150
{

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

Lines changed: 13 additions & 11 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;
@@ -21,7 +22,7 @@ namespace ActiveLogin.Authentication.BankId.AspNetCore.Areas.ActiveLogin.Control
2122
[NonController]
2223
public class BankIdUiSignApiController : BankIdUiApiControllerBase
2324
{
24-
private readonly IBankIdUiStateProtector _bankIdUiStateProtector;
25+
private readonly IStateStorage stateStorage;
2526

2627
public BankIdUiSignApiController(
2728
IBankIdFlowService bankIdFlowService,
@@ -31,10 +32,10 @@ public BankIdUiSignApiController(
3132
IBankIdUserMessage bankIdUserMessage,
3233
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
3334
IBankIdUiResultProtector uiAuthResultProtector,
34-
IBankIdUiStateProtector bankIdUiStateProtector)
35-
: base(bankIdFlowService, orderRefProtector, qrStartStateProtector, uiOptionsProtector, bankIdUserMessage, bankIdUserMessageLocalizer, uiAuthResultProtector)
35+
IStateStorage stateStorage
36+
) : base(bankIdFlowService, orderRefProtector, qrStartStateProtector, uiOptionsProtector, bankIdUserMessage, bankIdUserMessageLocalizer, uiAuthResultProtector)
3637
{
37-
_bankIdUiStateProtector = bankIdUiStateProtector;
38+
this.stateStorage = stateStorage;
3839
}
3940

4041
[ValidateAntiForgeryToken]
@@ -46,8 +47,8 @@ public async Task<ActionResult<BankIdUiApiInitializeResponse>> Initialize(BankId
4647

4748
var uiOptions = UiOptionsProtector.Unprotect(request.UiOptions);
4849

49-
var state = GetStateFromCookie(uiOptions);
50-
if(state == null)
50+
var state = await GetState(uiOptions);
51+
if (state == null)
5152
{
5253
throw new InvalidOperationException(BankIdConstants.ErrorMessages.InvalidStateCookie);
5354
}
@@ -103,14 +104,15 @@ public async Task<ActionResult<BankIdUiApiInitializeResponse>> Initialize(BankId
103104
}
104105
}
105106

106-
private BankIdUiSignState? GetStateFromCookie(BankIdUiOptions uiOptions)
107+
private Task<BankIdUiSignState?> GetState(BankIdUiOptions uiOptions)
107108
{
108-
var protectedState = Request.Cookies[uiOptions.StateCookieName];
109-
if (protectedState == null)
109+
var cookie = Request.Cookies[uiOptions.StateKeyCookieName];
110+
if (cookie == null)
110111
{
111-
throw new InvalidOperationException(BankIdConstants.ErrorMessages.InvalidStateCookie);
112+
return Task.FromResult<BankIdUiSignState?>(null);
112113
}
113114

114-
return _bankIdUiStateProtector.Unprotect(protectedState) as BankIdUiSignState;
115+
var stateKey = new StateKey(cookie);
116+
return stateStorage.ReadAsync<BankIdUiSignState>(stateKey);
115117
}
116118
}

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

Lines changed: 8 additions & 5 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,19 +17,17 @@ 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 : BankIdUiControllerBase<BankIdUiSignState>
1621
{
1722
public BankIdUiSignController(
1823
IAntiforgery antiforgery,
1924
IStringLocalizer<ActiveLoginResources> localizer,
2025
IBankIdUserMessageLocalizer bankIdUserMessageLocalizer,
2126
IBankIdUiOptionsProtector uiOptionsProtector,
2227
IBankIdInvalidStateHandler bankIdInvalidStateHandler,
23-
IBankIdUiStateProtector bankIdUiStateProtector
24-
)
25-
: base(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler, bankIdUiStateProtector)
28+
IStateStorage stateStorage
29+
) : base(antiforgery, localizer, bankIdUserMessageLocalizer, uiOptionsProtector, bankIdInvalidStateHandler, stateStorage)
2630
{
27-
2831
}
2932

3033
[HttpGet]

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

Lines changed: 2 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,7 @@ private static void AddBankIdAuthDefaultServices(IBankIdAuthBuilder builder)
7273

7374
BankIdCommonConfiguration.AddDefaultServices(services);
7475

75-
services.AddTransient<IBankIdUiStateProtector, BankIdUiStateProtector>();
76+
services.AddSingleton<IStateStorage, InMemoryStateStorage>();
7677
services.AddTransient<IBankIdUiResultProtector, BankIdUiResultProtector>();
7778

7879
builder.AddClaimsTransformer<BankIdDefaultClaimsTransformer>();

0 commit comments

Comments
 (0)