Skip to content

Releases: DuendeSoftware/products

IdentityServer 7.3.2

17 Sep 16:58
7d3159f

Choose a tag to compare

This is a patch release that optimizes key creation when not using X509 Certificates.

Details

  • Do not unnecessarily request current issuer when creating new key

IdentityServer 7.3.1

15 Aug 22:16
d487bfb

Choose a tag to compare

This is a patch release that fixes a bug and enables a System.Text.Json serialization option.

Details

  • Fixed an issue where uncommon license features caused an exception.
  • Allow RespectNullableAnnotationsDefault to be globally enabled. This is a relatively new feature in System.Text.Json that can be globally opted in to.

Templates 1.1.0

14 Aug 12:28
f2cd049

Choose a tag to compare

This is a significant update to the Duende.Templates package. Highlights include:

  • New duende-is template. This new template improves the experience for new users with an improved admin UI with wizards to create client and scope configuration, a new admin dashboard, explanatory text throughout, and updated visuals.
  • Use of IdentityServer 7.3.0 throughout all IdentityServer templates

IdentityServer 7.3.0

14 Aug 12:29
95362f6

Choose a tag to compare

IdentityServer 7.3.0 is a significant release that includes:

  • FAPI 2.0 profile certification
  • JWT Response from the introspection endpoint (RFC 9701)
  • Diagnostic data
  • Removal of the experimental label from OpenTelemetry metrics
  • Additional license compliance warnings
  • Several bug fixes
  • Numerous small code quality and performance enhancements from the community

Breaking Changes

There are no schema changes needed for IdentityServer 7.3.0. Small code changes maybe be required for some users to upgrade.

  • The SendLogoutNotificationAsync method has been removed from the DefaultBackChannelLogoutService class
  • Client Secret is now required for Clients with ClientCredentials Grant

The SendLogoutNotificationAsync method has been removed from the DefaultBackChannelLogoutService class

  • Fix Concurrent DbContext Access on Back Channel Logout by @bhazen in https://github.com/DuendeSoftware/products/pull/2019
    To fix a bug where when using EntityFramework, code which previously executed in parallel needed to be modified to execute sequentially. This necessitated the removal of the SendLogoutNotificationAsync method in the DefaultBackChannelLogoutService class. Anyone who had previously overridden the SendLogoutNotificationAsync as an extensibility point will likely need to move their customization to the PostLogoutJwt method.

Client Secret is now required for Clients with ClientCredentials Grant

  • Ensure Client Secret is Required for Clients with ClientCredentials Grant by @bhazen in https://github.com/DuendeSoftware/products/pull/1796
    Previously, it was possible to configure a Client to allow the ClientCredentials Grant without requiring a client secret which is undesirable. The default validation of Clients has been updated to ensure any Client which allows the ClientCredentials grant also sets the RequireClientSecret flag to true to disallow the configuration of a private client to behave like a public client.

Enhancements

FAPI 2.0 Profile Certification

IdentityServer is 7.3.0 is officially certified as conformant with the FAPI 2.0 Security Profile.

JWT Response from Introspection Endpoint

IdentityServer now supports RFC 9701 to return a JWT Response from the Introspection endpoint.

Diagnostic Data

Diagnostic data has been added to IdentityServer to help support with troubleshooting. Read more about this new feature in our docs. TODO: link to docs

Move OpenTelemetry Metrics from Experimental to Stable

Update License Usage Warnings

New warnings have been added around license compliance to help identify misuse of IdentityServer licenses prior to more strict license enforcement in the future.

Bug Fixes

Code Quality

Read more

Duende.AspNetCore.Authentication.JwtBearer 0.2.0

01 Aug 15:17
66feabe

Choose a tag to compare

This is a minor release focused primarily on improving support around DPoP to enable conformance with the FAPI 2.0 Security Profile. This release also includes a rework of the extensibility model offered by this package.

Breaking Changes

  • The extensibility model of this package has been worked in #1994 to make many types internal with then intention of making the intended extensibility points more explicit.

Detailed Changes

  • Make DPoP authorization scheme case-insensitive in #1969 by @josephdecock
  • Add more logging to dpop jwt events and validator in #1971 by @josephdecock
  • DPoP Jwt Bearer extensibility reworked in #1994 by @josephdecock
  • DPoP Error Handling in JwtBearerExtensions in #2005 by @bhazen

IdentityServer 7.3.0 Release Candidate 2

25 Jul 00:25
95362f6

Choose a tag to compare

This is the second release candidate for IdentityServer 7.3.0, containing several bug fixes from 7.2 releases that were missed in the first release candidate, as well as editorial changes to some new log messages.

Detailed change log

Previously fixed bugs

Log messages

Duende.Bff V4 - RC.1

24 Jul 13:56
8d41112

Choose a tag to compare

Duende.Bff V4 - RC.1 Pre-release
Pre-release

This release is a major change from the previous release. The biggest improvement here is multi-frontend support.

The extensibility approach has been drastically changed. To reduce the public API surface, and improve our ability to evolve the library, we no longer make every class in the system public with virtual methods. Implementation logic now is internal.

Changes and improvements

Changes since preview 2:

  • BffBuilder type (returned from services.AddBff()) is now an interface called IBffServicesBuilder. This is used as the basis for extension methods.

  • IBffServicesBuilder.WithDefaultCookieOptions is now called IBffServicesBuilder.ConfigureCookies()

  • IBffServicesBuilder.WithDefaultOpenIdConnectOptions is now called IBffServicesBuilder.ConfigureOpenIdConnect()

  • To support split host login scenarios', you can use a referer header in the Silent Login, coupled with BffOptions.AllowedSilentLoginReferers to create a list of allowed referers.

  • IFrontendCollection no longer exposes a GetAll method, but now implements IEnumerable.

  • ReturnUrlValidator.IsValidAsync now only accepts a uri

  • User sessions are now partitioned per frontend. IUserSessionStore has been updated to reflect this change. Note, you will have to run a migration to rename the column "ApplicationName" to "PartitionKey", including corresponding interfaces. Note, the migrations project has been updated to reflect this change.

  • When you add EntityFramework based sessions to your system, it no longer automatically enables session cleanup. The property BffOptions.EnableSessionCleanup is removed. You now have to call AddSessionCleanupBackgroundProcess() to enable session migration.

Changes since preview 1:

Upgrade guide

This release introduces many breaking changes. Some small, some large. We'll do our best to document how to upgrade here. Should you run into an upgrade issue that's not documented, please reach out to our discussion forum and we'll do our best to help.

Remote APIs

The syntax for configuring remote APIs has changed slightly:

// Use a client credentials token
app.MapRemoteBffApiEndpoint("/api/client-token", "https://localhost:5010")
-    .RequireAccessToken(TokenType.Client);
+    .WithAccessToken(RequiredTokenType.Client);      

// Use the client token only if the user is logged in
app.MapRemoteBffApiEndpoint("/api/optional-user-token", "https://localhost:5010")
-    .WithOptionalUserAccessToken();
+    .WithAccessToken(RequiredTokenType.UserOrNone);            
  • The enum TokenType has been renamed to RequiredTokenType.
  • The method to require the token type is renamed to WithAccessToken()
  • Requesting an optional access token should not be done with the method WithOptionalUserAccessToken() but with RequiredTokenType.UserOrNone

Configuring Token Types In YARP

The required token type configuration in yarp has also changed slightly. It uses the enum values from RequiredTokenType.

Extending The BFF

Simplified Wireup Without Explicit Authentication Setup

The V3 style of wireup still works, but BFF V4 comes with a newer style of wireup:

services.AddBff()
    .WithDefaultOpenIdConnectOptions(options =>
    {
        options.Authority = "your authority";
        options.ClientId = "your client id";
        options.ClientSecret = "secret";
        // ... other OpenID Connect options. 
    }
    .WithDefaultCookieOptions(options => {
        // The cookie options are automatically configured with recommended practices.
        // However, you can change the config here. 
    };

Adding this will automatically configure a Cookie and OpenID Connect flow.

Adding Multiple Frontends

You can statically add a list of frontends by calling the AddFrontends method.

.AddFrontends(
    new BffFrontend(BffFrontendName.Parse("default-frontend"))
        .WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html")),

    new BffFrontend(BffFrontendName.Parse("with-path"))
        .WithOpenIdConnectOptions(opt =>
        {
            opt.ClientId = "bff.multi-frontend.with-path";
            opt.ClientSecret = "secret";
        })
        .WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html"))
        .MappedToPath(LocalPath.Parse("/with-path")),

    new BffFrontend(BffFrontendName.Parse("with-domain"))
        .WithOpenIdConnectOptions(opt =>
        {
            opt.ClientId = "bff.multi-frontend.with-domain";
            opt.ClientSecret = "secret";
        })
        .WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html"))
        .MappedToOrigin(Origin.Parse("https://app1.localhost:5005"))
        .WithRemoteApis(
            new RemoteApi(LocalPath.Parse("/api/user-token"), new Uri("https://localhost:5010")),
            new RemoteApi(LocalPath.Parse("/api/client-token"), new Uri("https://localhost:5010"))
)

Loading Configuration From IConfiguration

Loading configuration, including openid connect configuration from an IConfiguration is now supported:

services.AddBff().LoadConfiguration(bffConfig);

Using this, you can configure your openid connect options, including secrets and configure the list of frontends. This also adds a file watcher, to automatically add / remove frontends from the config file.

See the type BffConfiguration to see what settings can be configured.

Index HTML Retrieval

It's fairly common to deploy your application in such a way to have the BFF be the first entrypoint for your application. It should serve an index.html that will bootstrap your frontend. However, your static content should be loaded from a CDN.

If you publish your frontend code to a cdn with absolute paths (for example by specifying a base path in your vite config), then all static content is loaded directly from the CDN.

You can configure the location of your Index HTML by specifying:

.WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html"))

Running migrations to usersession db.

A partition key has been added to the usersession db, to support the multi-frontend feature. If you're using the entity framework UserSessionDb provider, you'll need to run the migrations.

cd .\bff\migrations\UserSessionDb
dotnet tool install --global dotnet-ef
dotnet ef database update

Alternatively, here's the script to update the migrations for SqlLocalDB. It may have to be slightly adjusted to match your database of choice.

BEGIN TRANSACTION;

ALTER TABLE "UserSessions" RENAME COLUMN "ApplicationName" TO "PartitionKey";

DROP INDEX "IX_UserSessions_ApplicationName_SubjectId_SessionId";

CREATE UNIQUE INDEX "IX_UserSessions_PartitionKey_SubjectId_SessionId" ON "UserSessions" ("PartitionKey", "SubjectId", "SessionId");

DROP INDEX "IX_UserSessions_ApplicationName_SessionId";

CREATE UNIQUE INDEX "IX_UserSessions_PartitionKey_SessionId" ON "UserSessions" ("PartitionKey", "SessionId");

DROP INDEX "IX_UserSessions_ApplicationName_Key";

CREATE UNIQUE INDEX "IX_UserSessions_PartitionKey_Key" ON "UserSessions" ("PartitionKey", "Key");

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20250701130814_PartitionKey', '8.0.11');

COMMIT;

Duende.Bff V4 - Preview 3

16 Jul 15:05
9bdde60

Choose a tag to compare

Pre-release

This release is a major change from the previous release. The biggest improvement here is multi-frontend support.

The extensibility approach has been drastically changed. To reduce the public API surface, and improve our ability to evolve the library, we no longer make every class in the system public with virtual methods. Implementation logic now is internal.

Changes and improvements

Changes since preview 2:

  • BffBuilder type (returned from services.AddBff()) is now an interface called IBffServicesBuilder. This is used as the basis for extension methods.

  • IBffServicesBuilder.WithDefaultCookieOptions is now called IBffServicesBuilder.ConfigureCookies()

  • IBffServicesBuilder.WithDefaultOpenIdConnectOptions is now called IBffServicesBuilder.ConfigureOpenIdConnect()

  • To support split host login scenarios', you can use a referer header in the Silent Login, coupled with BffOptions.AllowedSilentLoginReferers to create a list of allowed referers.

  • IFrontendCollection no longer exposes a GetAll method, but now implements IEnumerable.

  • ReturnUrlValidator.IsValidAsync now only accepts a uri

  • User sessions are now partitioned per frontend. IUserSessionStore has been updated to reflect this change. Note, you will have to run a migration to rename the column "ApplicationName" to "PartitionKey", including corresponding interfaces. Note, the migrations project has been updated to reflect this change.

  • When you add EntityFramework based sessions to your system, it no longer automatically enables session cleanup. The property BffOptions.EnableSessionCleanup is removed. You now have to call AddSessionCleanupBackgroundProcess() to enable session migration.

Changes since preview 1:

Upgrade guide

This release introduces many breaking changes. Some small, some large. We'll do our best to document how to upgrade here. Should you run into an upgrade issue that's not documented, please reach out to our discussion forum and we'll do our best to help.

Remote APIs

The syntax for configuring remote APIs has changed slightly:

// Use a client credentials token
app.MapRemoteBffApiEndpoint("/api/client-token", "https://localhost:5010")
-    .RequireAccessToken(TokenType.Client);
+    .WithAccessToken(RequiredTokenType.Client);      

// Use the client token only if the user is logged in
app.MapRemoteBffApiEndpoint("/api/optional-user-token", "https://localhost:5010")
-    .WithOptionalUserAccessToken();
+    .WithAccessToken(RequiredTokenType.UserOrNone);            
  • The enum TokenType has been renamed to RequiredTokenType.
  • The method to require the token type is renamed to WithAccessToken()
  • Requesting an optional access token should not be done with the method WithOptionalUserAccessToken() but with RequiredTokenType.UserOrNone

Configuring Token Types In YARP

The required token type configuration in yarp has also changed slightly. It uses the enum values from RequiredTokenType.

Extending The BFF

Simplified Wireup Without Explicit Authentication Setup

The V3 style of wireup still works, but BFF V4 comes with a newer style of wireup:

services.AddBff()
    .WithDefaultOpenIdConnectOptions(options =>
    {
        options.Authority = "your authority";
        options.ClientId = "your client id";
        options.ClientSecret = "secret";
        // ... other OpenID Connect options. 
    }
    .WithDefaultCookieOptions(options => {
        // The cookie options are automatically configured with recommended practices.
        // However, you can change the config here. 
    };

Adding this will automatically configure a Cookie and OpenID Connect flow.

Adding Multiple Frontends

You can statically add a list of frontends by calling the AddFrontends method.

.AddFrontends(
    new BffFrontend(BffFrontendName.Parse("default-frontend"))
        .WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html")),

    new BffFrontend(BffFrontendName.Parse("with-path"))
        .WithOpenIdConnectOptions(opt =>
        {
            opt.ClientId = "bff.multi-frontend.with-path";
            opt.ClientSecret = "secret";
        })
        .WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html"))
        .MappedToPath(LocalPath.Parse("/with-path")),

    new BffFrontend(BffFrontendName.Parse("with-domain"))
        .WithOpenIdConnectOptions(opt =>
        {
            opt.ClientId = "bff.multi-frontend.with-domain";
            opt.ClientSecret = "secret";
        })
        .WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html"))
        .MappedToOrigin(Origin.Parse("https://app1.localhost:5005"))
        .WithRemoteApis(
            new RemoteApi(LocalPath.Parse("/api/user-token"), new Uri("https://localhost:5010")),
            new RemoteApi(LocalPath.Parse("/api/client-token"), new Uri("https://localhost:5010"))
)

Loading Configuration From IConfiguration

Loading configuration, including openid connect configuration from an IConfiguration is now supported:

services.AddBff().LoadConfiguration(bffConfig);

Using this, you can configure your openid connect options, including secrets and configure the list of frontends. This also adds a file watcher, to automatically add / remove frontends from the config file.

See the type BffConfiguration to see what settings can be configured.

Index HTML Retrieval

It's fairly common to deploy your application in such a way to have the BFF be the first entrypoint for your application. It should serve an index.html that will bootstrap your frontend. However, your static content should be loaded from a CDN.

If you publish your frontend code to a cdn with absolute paths (for example by specifying a base path in your vite config), then all static content is loaded directly from the CDN.

You can configure the location of your Index HTML by specifying:

.WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html"))

Running migrations to usersession db.

A partition key has been added to the usersession db, to support the multi-frontend feature. If you're using the entity framework UserSessionDb provider, you'll need to run the migrations.

cd .\bff\migrations\UserSessionDb
dotnet tool install --global dotnet-ef
dotnet ef database update

Alternatively, here's the script to update the migrations for SqlLocalDB. It may have to be slightly adjusted to match your database of choice.

BEGIN TRANSACTION;

ALTER TABLE "UserSessions" RENAME COLUMN "ApplicationName" TO "PartitionKey";

DROP INDEX "IX_UserSessions_ApplicationName_SubjectId_SessionId";

CREATE UNIQUE INDEX "IX_UserSessions_PartitionKey_SubjectId_SessionId" ON "UserSessions" ("PartitionKey", "SubjectId", "SessionId");

DROP INDEX "IX_UserSessions_ApplicationName_SessionId";

CREATE UNIQUE INDEX "IX_UserSessions_PartitionKey_SessionId" ON "UserSessions" ("PartitionKey", "SessionId");

DROP INDEX "IX_UserSessions_ApplicationName_Key";

CREATE UNIQUE INDEX "IX_UserSessions_PartitionKey_Key" ON "UserSessions" ("PartitionKey", "Key");

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20250701130814_PartitionKey', '8.0.11');

COMMIT;

IdentityServer 7.3.0 Release Candidate 1

02 Jul 18:02
28e5877

Choose a tag to compare

This is release candidate 1 of IdentityServer 7.3.0, a significant release that includes:

  • FAPI 2.0 profile certification
  • JWT Response from the introspection endpoint (RFC 9701)
  • Diagnostic data
  • Removal of the experimental label from OpenTelemetry metrics
  • Additional license compliance warnings
  • Several bug fixes
  • Numerous small code quality and performance enhancements from the community

Breaking Changes

There are no schema changes needed for IdentityServer 7.3.0. Small code changes maybe be required for some users to upgrade.

  • The SendLogoutNotificationAsync method has been removed from the DefaultBackChannelLogoutService class
  • Client Secret is now required for Clients with ClientCredentials Grant

The SendLogoutNotificationAsync method has been removed from the DefaultBackChannelLogoutService class

  • Fix Concurrent DbContext Access on Back Channel Logout by @bhazen in https://github.com/DuendeSoftware/products/pull/2019
    To fix a bug where when using EntityFramework, code which previously executed in parallel needed to be modified to execute sequentially. This necessitated the removal of the SendLogoutNotificationAsync method in the DefaultBackChannelLogoutService class. Anyone who had previously overridden the SendLogoutNotificationAsync as an extensibility point will likely need to move their customization to the PostLogoutJwt method.

Client Secret is now required for Clients with ClientCredentials Grant

  • Ensure Client Secret is Required for Clients with ClientCredentials Grant by @bhazen in https://github.com/DuendeSoftware/products/pull/1796
    Previously, it was possible to configure a Client to allow the ClientCredentials Grant without requiring a client secret which is undesirable. The default validation of Clients has been updated to ensure any Client which allows the ClientCredentials grant also sets the RequireClientSecret flag to true to disallow the configuration of a private client to behave like a public client.

Enhancements

FAPI 2.0 Profile Certification

IdentityServer is 7.3.0 is officially certified as conformant with the FAPI 2.0 Security Profile.

JWT Response from Introspection Endpoint

IdentityServer now supports RFC 9701 to return a JWT Response from the Introspection endpoint.

Diagnostic Data

Diagnostic data has been added to IdentityServer to help support with troubleshooting. Read more about this new feature in our docs. TODO: link to docs

Move OpenTelemetry Metrics from Experimental to Stable

Update License Usage Warnings

New warnings have been added around license compliance to help identify misuse of IdentityServer licenses prior to more strict license enforcement in the future.

Bug Fixes

Code Quality

Read more

BFF 4.0.0 preview 2

13 Jun 13:32
1f7fe82

Choose a tag to compare

BFF 4.0.0 preview 2 Pre-release
Pre-release

This release is a major change from the previous release. The biggest improvement here is multi-frontend support.

The extensibility approach has been drastically changed. To reduce the public API surface, and improve our ability to evolve the library, we no longer make every class in the system public with virtual methods. Implementation logic now is internal.

Changes and improvements

Changes since preview 1:

Upgrade guide

This release introduces many breaking changes. Some small, some large. We'll do our best to document how to upgrade here. Should you run into an upgrade issue that's not documented, please reach out to our discussion forum and we'll do our best to help.

Remote APIs

The syntax for configuring remote APIs has changed slightly:

// Use a client credentials token
app.MapRemoteBffApiEndpoint("/api/client-token", "https://localhost:5010")
-    .RequireAccessToken(TokenType.Client);
+    .WithAccessToken(RequiredTokenType.Client);      

// Use the client token only if the user is logged in
app.MapRemoteBffApiEndpoint("/api/optional-user-token", "https://localhost:5010")
-    .WithOptionalUserAccessToken();
+    .WithAccessToken(RequiredTokenType.UserOrNone);            
  • The enum TokenType has been renamed to RequiredTokenType.
  • The method to require the token type is renamed to WithAccessToken()
  • Requesting an optional access token should not be done with the method WithOptionalUserAccessToken() but with RequiredTokenType.UserOrNone

Configuring Token Types In YARP

The required token type configuration in yarp has also changed slightly. It uses the enum values from RequiredTokenType.

Extending The BFF

Simplified Wireup Without Explicit Authentication Setup

The V3 style of wireup still works, but BFF V4 comes with a newer style of wireup:

services.AddBff()
    .WithDefaultOpenIdConnectOptions(options =>
    {
        options.Authority = "your authority";
        options.ClientId = "your client id";
        options.ClientSecret = "secret";
        // ... other OpenID Connect options. 
    }
    .WithDefaultCookieOptions(options => {
        // The cookie options are automatically configured with recommended practices.
        // However, you can change the config here. 
    };

Adding this will automatically configure a Cookie and OpenID Connect flow.

Adding Multiple Frontends

You can statically add a list of frontends by calling the AddFrontends method.

.AddFrontends(
    new BffFrontend(BffFrontendName.Parse("default-frontend"))
        .WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html")),

    new BffFrontend(BffFrontendName.Parse("with-path"))
        .WithOpenIdConnectOptions(opt =>
        {
            opt.ClientId = "bff.multi-frontend.with-path";
            opt.ClientSecret = "secret";
        })
        .WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html"))
        .MappedToPath(LocalPath.Parse("/with-path")),

    new BffFrontend(BffFrontendName.Parse("with-domain"))
        .WithOpenIdConnectOptions(opt =>
        {
            opt.ClientId = "bff.multi-frontend.with-domain";
            opt.ClientSecret = "secret";
        })
        .WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html"))
        .MappedToOrigin(Origin.Parse("https://app1.localhost:5005"))
        .WithRemoteApis(
            new RemoteApi(LocalPath.Parse("/api/user-token"), new Uri("https://localhost:5010")),
            new RemoteApi(LocalPath.Parse("/api/client-token"), new Uri("https://localhost:5010"))
)

Loading Configuration From IConfiguration

Loading configuration, including openid connect configuration from an IConfiguration is now supported:

services.AddBff().LoadConfiguration(bffConfig);

Using this, you can configure your openid connect options, including secrets and configure the list of frontends. This also adds a file watcher, to automatically add / remove frontends from the config file.

See the type BffConfiguration to see what settings can be configured.

Index HTML Retrieval

It's fairly common to deploy your application in such a way to have the BFF be the first entrypoint for your application. It should serve an index.html that will bootstrap your frontend. However, your static content should be loaded from a CDN.

If you publish your frontend code to a cdn with absolute paths (for example by specifying a base path in your vite config), then all static content is loaded directly from the CDN.

You can configure the location of your Index HTML by specifying:

.WithIndexHtmlUrl(new Uri("https://localhost:5005/static/index.html"))