Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions BREAKINGCHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ ___Note:___ We might, and will probably, miss to document some of this - if so -

## TOC

* [Version 13.0.0 (TBD)](#version-1300-tbd)
* [Version 12.0.0](#version-1200)
* [Version 11.0.0](#version-1100)
* [Version 10.0.0](#version-1000)
Expand All @@ -20,6 +21,30 @@ ___Note:___ We might, and will probably, miss to document some of this - if so -

------

## Version 13.0.0 (TBD)

Breaking changes between version 12.0.0 and 13.0.0

### Upgrade to Application Insights 3.x

`ActiveLogin.Authentication.BankId.AzureMonitor` now depends on `Microsoft.ApplicationInsights` 3.x. Application Insights 2.x and 3.x can't be mixed in the same application, so if you use `AddApplicationInsightsEventListener()` you must also upgrade the Application Insights packages in your application (for example `Microsoft.ApplicationInsights.AspNetCore`) to 3.x. Application Insights 3.x requires a connection string (not an instrumentation key) and fails at startup without one. See the [Application Insights migration guide](https://learn.microsoft.com/en-us/azure/azure-monitor/app/migrate-to-opentelemetry) for details.

### Age hint moved from customMeasurements to customDimensions

`AL_User_AgeHint` is no longer sent as a metric (`customMeasurements`). It is now sent as a string property in `customDimensions` on the same event. Update any queries or dashboards that read it:

```kql
// Before
UserAgeHint = toint(customMeasurements.AL_User_AgeHint)

// After
UserAgeHint = toint(customDimensions.AL_User_AgeHint)
```

The sample queries in [the monitor documentation](https://docs.activelogin.net/articles/monitor.html) have been updated.

---

## Version 12.0.0

Breaking changes between version 11.0.0 and 12.0.0
Expand Down
2 changes: 1 addition & 1 deletion docs/articles/bankid.md
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ services
});
```

By default it will use whatever InstrumentationKey is registered with the application. There are overloads available so you can customize this:
By default it will use whatever Application Insights connection string is registered with the application. There are overloads available so you can customize this:

```csharp
services
Expand Down
2 changes: 1 addition & 1 deletion docs/articles/monitor.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ customEvents
customEvents
| where name == "ActiveLogin_BankId_CollectCompleted"
| project
UserAgeHint = toint(customMeasurements.AL_User_AgeHint)
UserAgeHint = toint(customDimensions.AL_User_AgeHint)
| summarize AverageUserAge = avg(UserAgeHint)
```

Expand Down
2 changes: 1 addition & 1 deletion samples/AzureProvisioningSample/ActiveLogin.json
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@
"[resourceId('Microsoft.Insights/components', variables('insights_resource_name'))]"
],
"properties": {
"APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(resourceId('Microsoft.Insights/components', variables('insights_resource_name'))).InstrumentationKey]",
"APPLICATIONINSIGHTS_CONNECTION_STRING": "[reference(resourceId('Microsoft.Insights/components', variables('insights_resource_name'))).ConnectionString]",
"APPINSIGHTS_PORTALINFO": "ASP.NETCORE",
"APPINSIGHTS_PROFILERFEATURE_VERSION": "disabled",
"APPINSIGHTS_SNAPSHOTFEATURE_VERSION": "disabled"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.12" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.23.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="3.1.2" />
</ItemGroup>

</Project>
12 changes: 10 additions & 2 deletions samples/IdentityServer.ClientSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@
var environment = builder.Environment;


// Add telemetry
services.AddApplicationInsightsTelemetry(configuration);
// Add telemetry (Application Insights 3.x requires a connection string)
var applicationInsightsConnectionString = configuration["ApplicationInsights:ConnectionString"];
if (string.IsNullOrWhiteSpace(applicationInsightsConnectionString))
{
applicationInsightsConnectionString = configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"];
}
if (!string.IsNullOrWhiteSpace(applicationInsightsConnectionString))
{
services.AddApplicationInsightsTelemetry(configuration);
}

// Add authentication
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
Expand Down
2 changes: 1 addition & 1 deletion samples/IdentityServer.ClientSample/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
}
},
"ApplicationInsights": {
"InstrumentationKey": ""
"ConnectionString": ""
},
"ActiveLogin": {
"IdentityProvider": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@

<ItemGroup>
<PackageReference Include="Duende.IdentityServer" Version="8.0.9" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.23.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="10.0.12" />
<PackageReference Include="Microsoft.Extensions.Logging.ApplicationInsights" Version="2.23.0" />
</ItemGroup>

<ItemGroup>
Expand Down
32 changes: 22 additions & 10 deletions samples/IdentityServer.ServerSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,17 @@
var environment = builder.Environment;


// Add telemetry
services.AddApplicationInsightsTelemetry(configuration);
// Add telemetry (Application Insights 3.x requires a connection string)
var applicationInsightsConnectionString = configuration["ApplicationInsights:ConnectionString"];
if (string.IsNullOrWhiteSpace(applicationInsightsConnectionString))
{
applicationInsightsConnectionString = configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"];
}
var useApplicationInsights = !string.IsNullOrWhiteSpace(applicationInsightsConnectionString);
if (useApplicationInsights)
{
services.AddApplicationInsightsTelemetry(configuration);
}

// Configure cookie policy
services.Configure<CookiePolicyOptions>(options =>
Expand Down Expand Up @@ -83,17 +92,20 @@
.AddBankId(bankId =>
{
bankId.AddDebugEventListener();
bankId.AddApplicationInsightsEventListener(options =>
if (useApplicationInsights)
{
options.LogUserPersonalIdentityNumber = false;
options.LogUserPersonalIdentityNumberHints = true;
bankId.AddApplicationInsightsEventListener(options =>
{
options.LogUserPersonalIdentityNumber = false;
options.LogUserPersonalIdentityNumberHints = true;

options.LogUserNames = false;
options.LogUserBankIdIssueDate = false;
options.LogUserNames = false;
options.LogUserBankIdIssueDate = false;

options.LogDeviceIpAddress = false;
options.LogDeviceUniqueHardwareId = false;
});
options.LogDeviceIpAddress = false;
options.LogDeviceUniqueHardwareId = false;
});
}

bankId.UseQrCoderQrCodeGenerator();
bankId.UseUaParserDeviceDetection();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
@inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet
@using Microsoft.Extensions.DependencyInjection
@{
// Only registered when an Application Insights connection string is configured
var JavaScriptSnippet = Context.RequestServices.GetService<Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet>();
}
<!doctype html>
<html lang="en">
<head>
Expand Down Expand Up @@ -56,7 +60,10 @@
</style>

<!-- Application Insights -->
@Html.Raw(JavaScriptSnippet.FullScript)
@if (JavaScriptSnippet != null)
{
@Html.Raw(JavaScriptSnippet.FullScript)
}
</head>
<body>
@RenderBody()
Expand Down
2 changes: 1 addition & 1 deletion samples/IdentityServer.ServerSample/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
}
},
"ApplicationInsights": {
"InstrumentationKey": ""
"ConnectionString": ""
},
"ActiveLogin": {
"Clients": {
Expand Down
32 changes: 22 additions & 10 deletions samples/Standalone.MvcSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,17 @@
var configuration = builder.Configuration;
var environment = builder.Environment;

// Add telemetry
services.AddApplicationInsightsTelemetry(configuration);
// Add telemetry (Application Insights 3.x requires a connection string)
var applicationInsightsConnectionString = configuration["ApplicationInsights:ConnectionString"];
if (string.IsNullOrWhiteSpace(applicationInsightsConnectionString))
{
applicationInsightsConnectionString = configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"];
}
var useApplicationInsights = !string.IsNullOrWhiteSpace(applicationInsightsConnectionString);
if (useApplicationInsights)
{
services.AddApplicationInsightsTelemetry(configuration);
}

// Configure cookie policy
services.Configure<CookiePolicyOptions>(options =>
Expand All @@ -54,18 +63,21 @@
.AddBankId(bankId =>
{
bankId.AddDebugEventListener();
bankId.AddApplicationInsightsEventListener(options =>
if (useApplicationInsights)
{
options.LogUserPersonalIdentityNumber = false;
options.LogUserPersonalIdentityNumberHints = true;
bankId.AddApplicationInsightsEventListener(options =>
{
options.LogUserPersonalIdentityNumber = false;
options.LogUserPersonalIdentityNumberHints = true;

options.LogUserNames = false;
options.LogUserNames = false;

options.LogUserBankIdIssueDate = false;
options.LogUserBankIdIssueDate = false;

options.LogDeviceIpAddress = false;
options.LogDeviceUniqueHardwareId = false;
});
options.LogDeviceIpAddress = false;
options.LogDeviceUniqueHardwareId = false;
});
}

bankId.UseDeviceData(config =>
{
Expand Down
2 changes: 1 addition & 1 deletion samples/Standalone.MvcSample/Standalone.MvcSample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.23.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="3.1.2" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion samples/Standalone.MvcSample/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"AllowedHosts": "*",
"ApplicationInsights": {
"InstrumentationKey": ""
"ConnectionString": ""
},
"Logging": {
"LogLevel": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.23.0" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="3.1.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Globalization;

using ActiveLogin.Authentication.BankId.Api;
using ActiveLogin.Authentication.BankId.Core.Events;
using ActiveLogin.Authentication.BankId.Core.Events.Infrastructure;
Expand Down Expand Up @@ -257,10 +259,9 @@ public override Task HandleCancelFailureEvent(BankIdCancelErrorEvent e)

// Helpers

private Task Track(BankIdEvent e, Dictionary<string, string>? properties = null, Dictionary<string, double>? metrics = null, PersonalIdentityNumber? personalIdentityNumber = null, Exception? exception = null, BankIdSupportedDevice? detectedDevice = null, BankIdFlowOptions? bankIdOptions = null)
private Task Track(BankIdEvent e, Dictionary<string, string>? properties = null, PersonalIdentityNumber? personalIdentityNumber = null, Exception? exception = null, BankIdSupportedDevice? detectedDevice = null, BankIdFlowOptions? bankIdOptions = null)
{
var allProperties = properties == null ? new Dictionary<string, string>() : new Dictionary<string, string>(properties);
var allMetrics = metrics == null ? new Dictionary<string, double>() : new Dictionary<string, double>(metrics);

allProperties.Add(PropertyName_ProductName, e.ActiveLoginProductName);
allProperties.Add(PropertyName_ProductVersion, e.ActiveLoginProductVersion);
Expand All @@ -278,7 +279,7 @@ private Task Track(BankIdEvent e, Dictionary<string, string>? properties = null,

if (personalIdentityNumber != null)
{
AddPersonalIdentityNumberProperties(allProperties, allMetrics, personalIdentityNumber);
AddPersonalIdentityNumberProperties(allProperties, personalIdentityNumber);
}

if (detectedDevice != null)
Expand All @@ -294,15 +295,15 @@ private Task Track(BankIdEvent e, Dictionary<string, string>? properties = null,
allProperties.Add(PropertyName_BankIdErrorDetails, bankIdApiException.ErrorDetails);
}

_telemetryClient.TrackException(exception, allProperties, metrics);
_telemetryClient.TrackException(exception, allProperties);
}

_telemetryClient.TrackEvent(e.EventTypeName, allProperties, allMetrics);
_telemetryClient.TrackEvent(e.EventTypeName, allProperties);

return Task.CompletedTask;
}

private void AddPersonalIdentityNumberProperties(Dictionary<string, string> properties, Dictionary<string, double> metrics, PersonalIdentityNumber personalIdentityNumber)
private void AddPersonalIdentityNumberProperties(Dictionary<string, string> properties, PersonalIdentityNumber personalIdentityNumber)
{
if (_options.LogUserPersonalIdentityNumber)
{
Expand All @@ -317,7 +318,7 @@ private void AddPersonalIdentityNumberProperties(Dictionary<string, string> prop
var ageHint = personalIdentityNumber?.GetAgeHint();
if (ageHint != null)
{
metrics.Add(PropertyName_UserAgeHint, ageHint.Value);
properties.Add(PropertyName_UserAgeHint, ageHint.Value.ToString(CultureInfo.InvariantCulture));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;

namespace ActiveLogin.Authentication.BankId.AzureMonitor;

/// <summary>
/// Owns a <see cref="TelemetryConfiguration"/> and <see cref="TelemetryClient"/> created from a connection string,
/// so that buffered telemetry is flushed and the configuration is disposed when the container is disposed.
/// </summary>
internal sealed class BankIdApplicationInsightsTelemetryClientProvider : IDisposable
{
private readonly TelemetryConfiguration _telemetryConfiguration;
private bool _disposed;

public BankIdApplicationInsightsTelemetryClientProvider(string connectionString)
{
_telemetryConfiguration = new TelemetryConfiguration
{
ConnectionString = connectionString
};
TelemetryClient = new TelemetryClient(_telemetryConfiguration);
}

public TelemetryClient TelemetryClient { get; }

public void Dispose()
{
if (_disposed)
{
return;
}

_disposed = true;
try
{
TelemetryClient.Flush();
}
finally
{
_telemetryConfiguration.Dispose();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using ActiveLogin.Authentication.BankId.Core.Events.Infrastructure;

using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Extensions.DependencyInjection;

namespace ActiveLogin.Authentication.BankId.AzureMonitor;
Expand Down Expand Up @@ -80,12 +79,12 @@ public static IBankIdBuilder AddApplicationInsightsEventListener(this IBankIdBui
/// <returns></returns>
public static IBankIdBuilder AddApplicationInsightsEventListener(this IBankIdBuilder builder, string connectionString, ApplicationInsightsBankIdEventListenerOptions options)
{
builder.Services.AddTransient<IBankIdEventListener>(x =>
{
var telemetryConfiguration = new TelemetryConfiguration();
telemetryConfiguration.ConnectionString = connectionString;
return new BankIdApplicationInsightsEventListener(new TelemetryClient(telemetryConfiguration), options);
});
// The listener is transient, so the configuration and client are owned by a singleton provider.
// The container disposes it on shutdown, which flushes buffered telemetry.
// The provider is keyed per call so that multiple registrations each use their own connection string.
var providerKey = new object();
builder.Services.AddKeyedSingleton(providerKey, (_, _) => new BankIdApplicationInsightsTelemetryClientProvider(connectionString));
builder.Services.AddTransient<IBankIdEventListener>(x => new BankIdApplicationInsightsEventListener(x.GetRequiredKeyedService<BankIdApplicationInsightsTelemetryClientProvider>(providerKey).TelemetryClient, options));

return builder;
}
Expand Down
Loading