Skip to content

Commit

Permalink
Merge branch 'main' into feature/365-ip-and-policy
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterOrneholm authored Apr 30, 2024
2 parents 395aeea + f62ec85 commit 919685e
Show file tree
Hide file tree
Showing 23 changed files with 227 additions and 171 deletions.
15 changes: 14 additions & 1 deletion BREAKINGCHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ ___Note:___ We might, and will probably, miss to document some of this - if so -

## TOC

* [Version 9.0.0](#version-800)
* [Version 10.0.0](#version-1000)
* [Version 9.0.0](#version-900)
* [Version 8.0.0](#version-800)
* [Version 7.0.0](#version-700)
* [Version 6.0.3](#version-603)
Expand All @@ -17,6 +18,18 @@ ___Note:___ We might, and will probably, miss to document some of this - if so -

---

## Version 10.0.0

Breaking changes between version 10.0.0 and 9.0.0

* Remove policy handling from API library into Core
* Fall back to mobile BankID policy for OtherDevice flow
* Enum for setting policy instead of string


---


## Version 9.0.0

Breaking changes between version 9.0.0 and 8.0.0
Expand Down
37 changes: 3 additions & 34 deletions docs/articles/bankid.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ The most common scenbario is to use Active Login for BankID auth/login, so most
* [Concepts](#concepts)
+ [Storing certificates in Azure](#storing-certificates-in-azure)
+ [Claims Issuing](#claims-issuing)
+ [BankID Certificate Policies](#bankid-certificate-policies)
+ [Return URL for cancellation](#return-url-for-cancellation)
+ [Handle missing or invalid state cookie](#handle-missing-or-invalid-state-cookie)
+ [Multi tenant scenario](#multi-tenant-scenario)
Expand Down Expand Up @@ -449,7 +448,8 @@ BankId options allows you to set and override some options such as these.
options.BankIdRequirePinCode = true;

// Limit possible login methods to, for example, only allow BankID on smartcard.
options.BankIdCertificatePolicies = BankIdCertificatePolicies.GetPoliciesForProductionEnvironment(...);
// If no policy is set, it will fall back to require mobile BankID for OtherDevice flow
options.BankIdCertificatePolicies = [ BankIdCertificatePolicy.BankIdOnFile, BankIdCertificatePolicy.BankIdOnSmartCard ];
});
```

Expand All @@ -458,7 +458,7 @@ If you want to apply some options for all BankID schemes, you can do so by using
```csharp
.Configure(options =>
{
options.BankIdCertificatePolicies = BankIdCertificatePolicies.GetPoliciesForProductionEnvironment(...);
options.BankIdRequireMrtd = true;
});
```

Expand Down Expand Up @@ -643,37 +643,6 @@ public class BankIdPinHintClaimsTransformer : IBankIdClaimsTransformer
```


### BankID Certificate Policies

BankId options allows you to set a list of certificate policies and there is a class available to help you out with this.

```csharp
.AddOtherDevice(options =>
{
options.BankIdCertificatePolicies = BankIdCertificatePolicies.GetPoliciesForProductionEnvironment(BankIdCertificatePolicy.BankIdOnFile, BankIdCertificatePolicy.MobileBankId);
});
```

Because the policies have different values for test and production environment, you need to use either `.GetPoliciesForProductionEnvironment()` or `.GetPoliciesForTestEnvironment()` depending on what environment you are using.

Example:

```csharp
.AddOtherDevice(options =>
{
var policies = new[] {
BankIdCertificatePolicy.BankIdOnFile,
BankIdCertificatePolicy.MobileBankId
};
if(isProductionEnvironment) {
options.BankIdCertificatePolicies = BankIdCertificatePolicies.GetPoliciesForProductionEnvironment(policies);
} else {
options.BankIdCertificatePolicies = BankIdCertificatePolicies.GetPoliciesForTestEnvironment(policies);
}
});
```


### Return URL for cancellation

If a user cancels the login, the user will be redirected to the `cancelReturnUrl`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<UserSecretsId>c579bda4-7b07-41ce-9586-a04cd72641fd</UserSecretsId>
</PropertyGroup>

<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions samples/Standalone.MvcSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using ActiveLogin.Authentication.BankId.AzureKeyVault;
using ActiveLogin.Authentication.BankId.AzureMonitor;
using ActiveLogin.Authentication.BankId.Core;
using ActiveLogin.Authentication.BankId.Core.CertificatePolicies;
using ActiveLogin.Authentication.BankId.QrCoder;
using ActiveLogin.Authentication.BankId.UaParser;

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using ActiveLogin.Authentication.BankId.Core.CertificatePolicies;

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;

Expand All @@ -16,7 +18,7 @@ public class BankIdAuthOptions : RemoteAuthenticationOptions
/// <summary>
/// The oid in certificate policies in the user certificate. List of String.
/// </summary>
public List<string> BankIdCertificatePolicies { get; set; } = new();
public List<BankIdCertificatePolicy> BankIdCertificatePolicies { get; set; } = new();

/// <summary>
/// Users are required to sign the transaction with their PIN code, even if they have biometrics activated.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ActiveLogin.Authentication.BankId.AspNetCore.Models;
using ActiveLogin.Authentication.BankId.Core.CertificatePolicies;

namespace ActiveLogin.Authentication.BankId.AspNetCore.DataProtection.Serialization;

Expand All @@ -24,6 +25,7 @@ protected override BankIdUiOptions Read(BinaryReader reader)
{
CertificatePoliciesSeparator
}, StringSplitOptions.RemoveEmptyEntries)
.Select(Enum.Parse<BankIdCertificatePolicy>)
.ToList();

return new BankIdUiOptions(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using ActiveLogin.Authentication.BankId.Core.CertificatePolicies;

namespace ActiveLogin.Authentication.BankId.AspNetCore.Models;

public class BankIdUiOptions
{
public BankIdUiOptions(
List<string> certificatePolicies,
List<BankIdCertificatePolicy> certificatePolicies,
bool sameDevice,
bool requirePinCode,
bool requireMrtd,
Expand All @@ -18,7 +20,7 @@ public BankIdUiOptions(
StateCookieName = stateCookieName;
}

public List<string> CertificatePolicies { get; }
public List<BankIdCertificatePolicy> CertificatePolicies { get; }

public bool SameDevice { get; }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using ActiveLogin.Authentication.BankId.Core.CertificatePolicies;

using Microsoft.AspNetCore.Http;

namespace ActiveLogin.Authentication.BankId.AspNetCore.Sign;
Expand All @@ -7,7 +9,7 @@ public class BankIdSignOptions
/// <summary>
/// The oid in certificate policies in the user certificate. List of String.
/// </summary>
public List<string> BankIdCertificatePolicies { get; set; } = new();
public List<BankIdCertificatePolicy> BankIdCertificatePolicies { get; set; } = new();

/// <summary>
/// Users are required to sign the transaction with their PIN code, even if they have biometrics activated.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace ActiveLogin.Authentication.BankId.Api.CertificatePolicies;
namespace ActiveLogin.Authentication.BankId.Core.CertificatePolicies;

public enum BankIdCertificatePolicy
{
Expand All @@ -17,11 +17,6 @@ public enum BankIdCertificatePolicy
/// </summary>
MobileBankId,

/// <summary>
/// Nordea e-id on file and on smart card.
/// </summary>
NordeaEidOnFileAndOnSmartCard,

/// <summary>
/// Test BankID for some BankID Banks.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace ActiveLogin.Authentication.BankId.Core.CertificatePolicies;

public class BankIdCertificatePolicyResolverForProduction : IBankIdCertificatePolicyResolver
{
public const string BankIdOnFileProductionEnvironment = "1.2.752.78.1.1";
public const string BankIdOnSmartCardProductionEnvironment = "1.2.752.78.1.2";
public const string MobileBankIdProductionEnvironment = "1.2.752.78.1.5";

public string Resolve(BankIdCertificatePolicy certificatePolicy)
{
return certificatePolicy switch
{
BankIdCertificatePolicy.BankIdOnFile => BankIdOnFileProductionEnvironment,
BankIdCertificatePolicy.BankIdOnSmartCard => BankIdOnSmartCardProductionEnvironment,
BankIdCertificatePolicy.MobileBankId => MobileBankIdProductionEnvironment,
BankIdCertificatePolicy.TestBankId => throw new NotSupportedException("Test BankID is not supported in production."),

_ => throw new ArgumentOutOfRangeException(nameof(certificatePolicy), certificatePolicy, "Unknown certificate policy")
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace ActiveLogin.Authentication.BankId.Core.CertificatePolicies;

public class BankIdCertificatePolicyResolverForTest : IBankIdCertificatePolicyResolver
{
public const string BankIdOnFileTestEnvironment = "1.2.3.4.5";
public const string BankIdOnSmartCardTestEnvironment = "1.2.3.4.10";
public const string MobileBankIdTestEnvironment = "1.2.3.4.25";
public const string TestBankIdTestEnvironment = "1.2.752.60.1.6";

public string Resolve(BankIdCertificatePolicy certificatePolicy)
{
return certificatePolicy switch
{
BankIdCertificatePolicy.BankIdOnFile => BankIdOnFileTestEnvironment,
BankIdCertificatePolicy.BankIdOnSmartCard => BankIdOnSmartCardTestEnvironment,
BankIdCertificatePolicy.MobileBankId => MobileBankIdTestEnvironment,
BankIdCertificatePolicy.TestBankId => TestBankIdTestEnvironment,

_ => string.Empty,
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ActiveLogin.Authentication.BankId.Core.CertificatePolicies;

public interface IBankIdCertificatePolicyResolver
{
public string Resolve(BankIdCertificatePolicy certificatePolicy);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using ActiveLogin.Authentication.BankId.Api;
using ActiveLogin.Authentication.BankId.Api.Models;
using ActiveLogin.Authentication.BankId.Api.UserMessage;
using ActiveLogin.Authentication.BankId.Core.CertificatePolicies;
using ActiveLogin.Authentication.BankId.Core.Events;
using ActiveLogin.Authentication.BankId.Core.Events.Infrastructure;
using ActiveLogin.Authentication.BankId.Core.Launcher;
Expand All @@ -27,6 +28,7 @@ public class BankIdFlowService : IBankIdFlowService
private readonly IBankIdAuthRequestUserDataResolver _bankIdAuthUserDataResolver;
private readonly IBankIdQrCodeGenerator _bankIdQrCodeGenerator;
private readonly IBankIdLauncher _bankIdLauncher;
private readonly IBankIdCertificatePolicyResolver _bankIdCertificatePolicyResolver;

public BankIdFlowService(
IBankIdAppApiClient bankIdAppApiClient,
Expand All @@ -38,7 +40,8 @@ public BankIdFlowService(
IBankIdEndUserIpResolver bankIdEndUserIpResolver,
IBankIdAuthRequestUserDataResolver bankIdAuthUserDataResolver,
IBankIdQrCodeGenerator bankIdQrCodeGenerator,
IBankIdLauncher bankIdLauncher
IBankIdLauncher bankIdLauncher,
IBankIdCertificatePolicyResolver bankIdCertificatePolicyResolver
)
{
_bankIdAppApiClient = bankIdAppApiClient;
Expand All @@ -51,6 +54,7 @@ IBankIdLauncher bankIdLauncher
_bankIdAuthUserDataResolver = bankIdAuthUserDataResolver;
_bankIdQrCodeGenerator = bankIdQrCodeGenerator;
_bankIdLauncher = bankIdLauncher;
_bankIdCertificatePolicyResolver = bankIdCertificatePolicyResolver;
}

public async Task<BankIdFlowInitializeResult> InitializeAuth(BankIdFlowOptions flowOptions, string returnRedirectUrl)
Expand Down Expand Up @@ -95,9 +99,9 @@ private async Task<AuthResponse> GetAuthResponse(BankIdFlowOptions flowOptions,
private async Task<AuthRequest> GetAuthRequest(BankIdFlowOptions flowOptions)
{
var endUserIp = _bankIdEndUserIpResolver.GetEndUserIp();
var certificatePolicies = flowOptions.CertificatePolicies.Any() ? flowOptions.CertificatePolicies : null;
var resolvedCertificatePolicies = GetResolvedCertificatePolicies(flowOptions);

var authRequestRequirement = new Requirement(certificatePolicies, flowOptions.RequirePinCode, flowOptions.RequireMrtd);
var authRequestRequirement = new Requirement(resolvedCertificatePolicies, flowOptions.RequirePinCode, flowOptions.RequireMrtd);

var authRequestContext = new BankIdAuthRequestContext(endUserIp, authRequestRequirement);
var userData = await _bankIdAuthUserDataResolver.GetUserDataAsync(authRequestContext);
Expand All @@ -110,7 +114,7 @@ private async Task<AuthRequest> GetAuthRequest(BankIdFlowOptions flowOptions)
userData.UserVisibleDataFormat
);
}

public async Task<BankIdFlowInitializeResult> InitializeSign(BankIdFlowOptions flowOptions, BankIdSignData bankIdSignData, string returnRedirectUrl)
{
var detectedUserDevice = _bankIdSupportedDeviceDetector.Detect();
Expand Down Expand Up @@ -153,8 +157,8 @@ private async Task<SignResponse> GetSignResponse(BankIdFlowOptions flowOptions,
private SignRequest GetSignRequest(BankIdFlowOptions flowOptions, BankIdSignData bankIdSignData)
{
var endUserIp = _bankIdEndUserIpResolver.GetEndUserIp();
var certificatePolicies = flowOptions.CertificatePolicies.Any() ? flowOptions.CertificatePolicies : null;
var requestRequirement = new Requirement(certificatePolicies, flowOptions.RequirePinCode, flowOptions.RequireMrtd, flowOptions.RequiredPersonalIdentityNumber?.To12DigitString());
var resolvedCertificatePolicies = GetResolvedCertificatePolicies(flowOptions);
var requestRequirement = new Requirement(resolvedCertificatePolicies, flowOptions.RequirePinCode, flowOptions.RequireMrtd, flowOptions.RequiredPersonalIdentityNumber?.To12DigitString());

return new SignRequest(
endUserIp,
Expand All @@ -165,6 +169,25 @@ private SignRequest GetSignRequest(BankIdFlowOptions flowOptions, BankIdSignData
);
}

private List<string>? GetResolvedCertificatePolicies(BankIdFlowOptions flowOptions)
{
var certificatePolicies = flowOptions.CertificatePolicies;
if (!certificatePolicies.Any())
{
if (!flowOptions.SameDevice)
{
// Enforce mobile bank id for other device if no other policy is set
certificatePolicies = [BankIdCertificatePolicy.MobileBankId];
}
else
{
return null;
}
}

return certificatePolicies.Select(x => _bankIdCertificatePolicyResolver.Resolve(x)).ToList();
}

private Task<BankIdLaunchInfo> GetBankIdLaunchInfo(string redirectUrl, string autoStartToken)
{
var launchUrlRequest = new LaunchUrlRequest(redirectUrl, autoStartToken);
Expand Down
Loading

0 comments on commit 919685e

Please sign in to comment.