# Duende IdentityServer v6.2 to v6.3

This upgrade guide covers upgrading from Duende IdentityServer v6.2 to v6.3 ([release notes](https://github.com/DuendeSoftware/products/releases/tag/is%2F6.3.0)).

Duende IdentityServer 6.3 adds:

* [Support](/identityserver/tokens/pop/#demonstrating-proof-of-possession-at-the-application-layer-dpop) for [OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP) ](https://datatracker.ietf.org/doc/draft-ietf-oauth-dpop/), a new OAuth specification for sender-constraining refresh tokens and access tokens.

* A new [Configuration API](/identityserver/configuration) distributed through the separate `Duende.IdentityServer.Configuration` NuGet package that supports the [OAuth](https://datatracker.ietf.org/doc/rfc7591/) and [OIDC](https://openid.net/specs/openid-connect-registration-1_0.html) Dynamic Client Registration specifications.

* Support for [3rd party initiated login](https://openid.net/specs/openid-connect-core-1_0.html#thirdpartyinitiatedlogin) through the new client configuration property `InitiateLoginUri`. This is typically used to create a [client application portal](/identityserver/ui/portal/) page within an IdentityServer host.

* [Support](/identityserver/reference/endpoints/authorize/#optional-parameters) for the OIDC `prompt=create` parameter, which gives the client application the ability to provide a hint that the user needs to register.

* New configuration options for [managing refresh token rotation](/identityserver/tokens/refresh/#accepting-consumed-tokens).

* Support for the `unmet_authentication_requirements` error response code, improving error responses during step-up flows.

* Nullable reference type annotations on many public APIs.

* Programmer quality of life improvements, bug fixes, and more! See the [release notes](https://github.com/DuendeSoftware/products/releases/tag/is%2F6.3.0) for more details.

## Step 1: Update NuGet package

[Section titled âStep 1: Update NuGet packageâ](#step-1-update-nuget-package)

In your IdentityServer host project, update the version of the NuGet package reference. For example in your project file:

```plaintext
<PackageReference Include="Duende.IdentityServer" Version="6.2.0" />
```

would change to:

```plaintext
<PackageReference Include="Duende.IdentityServer" Version="6.3.0" />
```

## Step 2: Update Database Schema (if necessary)

[Section titled âStep 2: Update Database Schema (if necessary)â](#step-2-update-database-schema-if-necessary)

IdentityServer 6.3 adds new four new properties to the [`Duende.IdentityServer.Models.Client` model](/identityserver/reference/models/client/) that are needed to support DPoP and 3rd party initiated login. If you are storing you Client configuration in a [database](/identityserver/data), then you will need to update the databaseâs schema.

* The `InitiateLoginUri` string is a nullable string used for Third Party Initiated Login. Existing clients only need a value set for this property if the IdentityServer host itself is using third party initiated login (e.g., if you are building a client application portal within your IdentityServer) and want the client to be part of the portal.

* New properties added to the Client Model for DPoP support:

  * `RequireDPoP` is a non-nullable boolean flag that controls if a client is required to use DPoP. Existing clients that are not using DPoP can set this to false.
  * `DPoPValidationMode` is a non-nullable column that stores a âflagsâ-style enum that controls the DPoP validation mechanism. In most databases, this is represented as an integer. Existing clients that are not using DPoP can set its value to 0.
  * `DPoPClockSkew` is a non-nullable timespan that controls how much clock skew is allowed for a particular DPoP client. Existing clients that are not using DPoP can set its value to a timespan of length 0.

IdentityServer is abstracted from the data store on multiple levels, so the exact steps involved in updating your data store will depend on your implementation details.

#### Custom Store Implementations

[Section titled âCustom Store Implementationsâ](#custom-store-implementations)

The core of IdentityServer is written against the [store interfaces](/identityserver/reference/stores), which abstract all the implementation details of actually storing data. If your IdentityServer implementation includes a custom implementation of those stores, then you will have to determine how best to include the changes in the model in the underlying data store and make any necessary changes to schemas, if your data store requires that.

#### Duende.IdentityServer.EntityFramework

[Section titled âDuende.IdentityServer.EntityFrameworkâ](#duendeidentityserverentityframework)

We also provide a default implementation of the stores in the `Duende.IdentityServer.EntityFramework` package, but this implementation is still highly abstracted because it is usable with any database that has an EF provider. Different database vendors have very different dialects of sql that have different syntax and type systems, so we donât provide schema changes directly. Instead, we provide the Entity Framework entities and mappings which can be used with Entity Frameworkâs migrations feature to generate the schema updates that are needed in your database.

To generate a migration for the new columns, run the command below. Note that you might need to adjust paths based on your specific organization of the migration files.

```plaintext
dotnet ef migrations add Update_DuendeIdentityServer_v6_3 -c ConfigurationDbContext -o Migrations/ConfigurationDb
```

Then to apply this migration to your database:

```plaintext
dotnet ef database update -c ConfigurationDbContext
```

Some organizations prefer to use other tools for managing schema changes. Youâre free to manage your schema however you see fit, as long as the entities can be successfully mapped. Even if youâre not going to ultimately use Entity Framework migrations to manage your database changes, generating a migration can be a useful development step to get an idea of what needs to be done.

## Step 3: Verify Data Protection Configuration

[Section titled âStep 3: Verify Data Protection Configurationâ](#step-3-verify-data-protection-configuration)

IdentityServer depends on ASP.NET Data Protection. Data Protection encrypts and signs data using keys managed by ASP.NET. Those keys are isolated by application name, which by default is set to the content root path of the host. This prevents multiple applications from sharing encryption keys, which is necessary to protect your encryption against certain forms of attack. However, this means that if your content root path changes, the default settings for data protection will prevent you from using your old keys. Beginning in .NET 6, the content root path was normalized so that it ends with a directory separator. In .NET 7 that change was reverted. This means that your content root path might change if you upgrade from .NET 6 to .NET 7. This can be mitigated by explicitly setting the application name and removing the separator character. See [Microsoftâs documentation for more information](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-7.0#setapplicationname).

## Step 4: Breaking changes

[Section titled âStep 4: Breaking changesâ](#step-4-breaking-changes)

* A new `ITokenCleanupService` interface has been extracted from the `TokenCleanupService`, and IdentityServer now depends on that interface, rather than the service itself. Customizations of `TokenCleanupService` that previously were implemented by deriving from that class and registering the derived class in the ASP.NET Core service provider need to

  * Register the derived class as an implementation of `ITokenCleanupService`, and
  * Remove the `IServerSideSessionsMarker` from any calls to the base constructor.

  See issue [#981](https://github.com/DuendeSoftware/products/issues/981).

* The `TokenCleanupService.RemoveExpiredGrantsAsync` method was renamed to `CleanupGrantsAsync` to reflect that it performs all grant cleanup work, including removing consumed grants and expired device codes in addition to expired grants. In the strictest sense, this is a breaking change, but it is very unlikely to cause issues during an upgrade because even though `RemoveExpiredGrantsAsync` was public, it was not virtual. If you were using `RemoveExpiredGrantsAsync` elsewhere, update your code to use the new name.

  See issue [#981](https://github.com/DuendeSoftware/products/issues/981).

* The value of the `typ` claim in the header of Logout tokens has changed to `logout+jwt`, which complies with OpenID Connect Back-Channel Logout 1.0. Clients that were previously validating the `typ` need to be updated, or the old `typ` can continue to be used via the new `LogoutTokenJwtType` configuration option.

  See issue [#1169](https://github.com/DuendeSoftware/products/issues/1169).

* The `TokenResponseGenerator.ProcessTokenRequestAsync` virtual method, which generates access and refresh tokens and adds them to a response object, is now called by all token flows except the refresh token flow. This unifies the programming and extensibility model of the generator, which previously had duplicated code in some flows. If you have overridden this virtual method, be aware that it will now be called in all flows. Previously, the authorization code flow, device code flow, and CIBA flow did not invoke this method.

  See pull request: [#1178](https://github.com/DuendeSoftware/products/pull/1178).

* One time use (rotated) refresh tokens are now deleted immediately when they are used by default. If you rely on the existing behavior of marking refresh tokens as consumed (perhaps to allow for lenient rotations or replay detection), set the new `PersistentGrantOptions.DeleteOneTimeOnlyRefreshTokensOnUse` option to false.

  See issue [#1102](https://github.com/DuendeSoftware/products/issues/1102).

## Step 5: Done!

[Section titled âStep 5: Done!â](#step-5-done)

Thatâs it. Of course, at this point you can and should test that your IdentityServer is updated and working properly.
-----