From 9f7ec910b751cc6435fd45b86aaa28f2bac66154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Dybvik=20Langfors?= Date: Tue, 15 Oct 2024 14:59:16 +0200 Subject: [PATCH] Fix ID-porten acr claim parsing --- .../Extensions/ClaimsPrincipalExtensions.cs | 21 +++++-- .../ClaimsPrincipalExtensionsTests.cs | 59 +++++++++++++++++++ 2 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs diff --git a/src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs b/src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs index abf33f878..28e4f4df8 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs @@ -174,17 +174,26 @@ public static bool TryGetOrganizationNumber(this Claim? consumerClaim, [NotNullW public static bool TryGetAuthenticationLevel(this ClaimsPrincipal claimsPrincipal, [NotNullWhen(true)] out int? authenticationLevel) { - foreach (var claimType in new[] { IdportenAuthLevelClaim, AltinnAuthLevelClaim }) + if (claimsPrincipal.TryGetClaimValue(AltinnAuthLevelClaim, out var claimValue) && int.TryParse(claimValue, out var level)) { - if (!claimsPrincipal.TryGetClaimValue(claimType, out var claimValue)) continue; - // The acr claim value is "LevelX" where X is the authentication level - var valueToParse = claimType == IdportenAuthLevelClaim ? claimValue[5..] : claimValue; - if (!int.TryParse(valueToParse, out var level)) continue; - authenticationLevel = level; return true; } + if (claimsPrincipal.TryGetClaimValue(IdportenAuthLevelClaim, out claimValue)) + { + // The acr claim value is either "idporten-loa-substantial" (previously "Level3") or "idporten-loa-high" (previously "Level4") + // https://docs.digdir.no/docs/idporten/oidc/oidc_protocol_new_idporten#new-acr-values + authenticationLevel = claimValue switch + { + "idporten-loa-substantial" => 3, + "idporten-loa-high" => 4, + _ => null + }; + + return authenticationLevel.HasValue; + } + authenticationLevel = null; return false; } diff --git a/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs b/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs new file mode 100644 index 000000000..8c2204bdc --- /dev/null +++ b/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs @@ -0,0 +1,59 @@ +using System.Security.Claims; +using Digdir.Domain.Dialogporten.Application.Common.Extensions; + +namespace Digdir.Domain.Dialogporten.Application.Unit.Tests.Features.V1.Common.Extensions; + +public class ClaimsPrincipalExtensionsTests +{ + [Fact] + public void TryGetAuthenticationLevel_Should_Parse_Idporten_Acr_Claim_For_Level3() + { + // Arrange + var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new[] + { + new Claim("acr", "idporten-loa-substantial") + })); + + // Act + var result = claimsPrincipal.TryGetAuthenticationLevel(out var authenticationLevel); + + // Assert + Assert.True(result); + Assert.Equal(3, authenticationLevel); + } + + [Fact] + public void TryGetAuthenticationLevel_Should_Parse_Idporten_Acr_Claim_For_Level4() + { + // Arrange + var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new[] + { + new Claim("acr", "idporten-loa-high") + })); + + // Act + var result = claimsPrincipal.TryGetAuthenticationLevel(out var authenticationLevel); + + // Assert + Assert.True(result); + Assert.Equal(4, authenticationLevel); + } + + [Fact] + public void TryGetAuthenticationLevel_Should_Parse_Altinn_Authlevel_First() + { + // Arrange + var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new[] + { + new Claim("acr", "idporten-loa-high"), + new Claim("urn:altinn:authlevel", "5") + })); + + // Act + var result = claimsPrincipal.TryGetAuthenticationLevel(out var authenticationLevel); + + // Assert + Assert.True(result); + Assert.Equal(5, authenticationLevel); + } +}