This is a significant release that adds support for DPoP, Dynamic Client Registration, improves refresh token handling, and adds many other new features and bug fixes.
Breaking Changes
-
A new
ITokenCleanupService
interface has been extracted from theTokenCleanupService
, and IdentityServer now depends on that interface, rather than the service itself. Customizations ofTokenCleanupService
that previously were implemented by deriving from that class and registering the derived class in the DI system 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.
- Register the derived class as an implementation of
-
The
TokenCleanupService.RemoveExpiredGrantsAsync
method was renamed toCleanupGrantsAsync
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 thoughRemoveExpiredGrantsAsync
was public, it was not virtual. If you were usingRemoveExpiredGrantsAsync
elsewhere, update your code to use the new name.See issue #981.
-
The value of the
typ
claim in the header of Logout tokens has changed tologout+jwt
, which complies with OpenID Connect Back-Channel Logout 1.0. Clients that were previously validating thetyp
need to be updated, or the oldtyp
can continue to be used via the newLogoutTokenJwtType
configuration option.See issue #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.
-
One time use (rotated) refresh tokens are now deleted immediately when they are used. 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.
Schema Changes
-
New InitiateLoginUri string property added to the Client model. This is a nullable string that can be left null for existing clients. This column is used for Third Party Initiated Login.
-
New properties added to the Client Model for DPoP support:
- RequireDPoP is a non-nullable boolean flag that requires a client to use DPoP. Existing clients can set this to false, unless you want the client to start using DPoP.
- 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 0.
DPoP
IdentityServer 6.3 adds support for OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP) , a new OAuth specification for sender-constraining refresh tokens and access tokens. DPoP tokens can only be used by the client application that they are issued to, which provides a strong defense against replay attacks.
Our blog post announcing the feature is here, and detailed documentation is here.
Configuration API/Dynamic Client Registration
IdentityServer 6.3 begins an effort to add programmatic configuration capabilities to IdentityServer. This configuration capability will take the form of a Configuration API that can be hosted either separately or within the IdentityServer implementation, and is distributed through the separate Duende.IdentityServer.Configuration nuget package.
This initial version of the Configuration API supports the OAuth and OIDC Dynamic Client Registration specifications, which allow a client or relying party to register their configuration details with IdentityServer dynamically by making standardized API requests. You could also use Dynamic Client Registration to provision environments automatically, perhaps in a deployment pipeline.
Our blog post announcing the feature is here, and detailed documentation is here.
See issue #111.
Client Application Portal
InitiateLoginUri
is a new optional property added to the IdentityServer Client model that can be used to initiate login from the IdentityServer host. Typically this is used to create an application portal within the IdentityServer host, with links to the registered client applications. The UI templates now include an example of this portal.
See issue #1124.
Initiate User Registration via OIDC
OIDC Relying Parties can now indicate that user registration is needed using the standardized prompt=create
parameter. To use this parameter, set the UserInteraction.CreateAccountUrl
option to the location of your account creation page. The UI templates now include an example user registration page.
Step-up Error Handling
OIDC Relying Parties can request particular requirements during authentication using the step-up process. For example, they might require two factor authentication before allowing a highly sensitive transaction. IdentityServer now supports the unmet_authentication_requirements
error response code during step-up, which can be returned if IdentityServer is unable to fullfil the step-up requirements. If you set the Error
property of a ConsentResponse
or AuthorizeResponse
to "unmet_authentication_requirements" (you can use IdentityModel.OidcConstants.AuthorizeErrors.UnmetAuthenticationRequirements
), IdentityServer will return the error to the client.
See issue #1133.
Refresh Token Cleanup
New configuration options (see below) have been added to control what happens to single use refresh tokens when they are used. If the new DeleteOneTimeOnlyRefreshTokensOnUse
flag is set, they will be immediately deleted. If you wish to keep consumed tokens for a period time for replay detection or to allow for leniency in the rotation policy, you can now add a delay using the ConsumedTokenCleanupDelay
, guaranteeing that consumed tokens will not be deleted for that amount of time.
See issues #1102, #1065, and #982.
New Configuration Options
-
PersistentGrantOptions.DeleteOneTimeOnlyRefreshTokensOnUse
controls what happens toRefreshTokenUsage.OneTime
refresh tokens when they are used. They can now be either marked as consumed or deleted immediately. The intent is that if you aren't making use of the consumed tokens you can safely delete them immediately. The default is to immediately delete.See issue #1102.
-
OperationalStoreOptions.ConsumedTokenCleanupDelay
delays deletion of consumed tokens in the token cleanup job. The intent of the delay is to allow users to keep tokens for some period of time to be used in some custom process. Custom code in theRefreshTokenService
could allow "lenient" one-time use refresh tokens that can be reused for a short interval or detect token replay attacks by checking if a token is reused inappropriately. The default value for this new option is 0.See issue #1102.
-
LogoutTokenJwtType
sets thetyp
claim in the header of logout tokens. Defaults tologout+jwt
, which complies with OpenID Connect Back-Channel Logout 1.0.See issue #1029.
-
UserInteraction.CreateAccountUrl
controls where the user is sent when theprompt=create
parameter is sent as part of an OIDC login flow. Setting this option enables support for that parameter and is reflected in theprompt_values_supported
property of the discovery document. If it is not set,prompt=create
will be ignored.See issue: #432.
-
DPoP.ProofTokenValidityDuration
sets the duration that DPoP proof tokens are considered valid. Defaults to 1 minute.See issue #1116
-
DPoP.ServerClockSkew
sets the clock skew used when validating DPoP proof token expiration using a server-generated nonce value. Defaults to 0.See issue #1116
Extensibility and Other Miscellaneous Improvements
-
IdentityServerConstants.ProtocolRoutePaths
constants are now publicly accessibleSee issue #1201.
-
Added
IdentityServerConstants.ContentSecurityPolicyHashes
constants to facilitate creation of content security policies.See issue #1183.
-
Added
ITokenCleanupService
interface extracted fromTokenCleanupService
, which can be used to customize token cleanup.See issue #981.
-
Added virtual method
ServerSideSessionStore.ApplyFilter
, which can be used to customize how server side sessions are queried. -
Added
logout_reason
claim to back-channel logout tokens, which describes why the logout token is being sent using the following values:user_logout
- the user interactively logged outsession_expiration
- the user's session expired due to inactivityterminated
- the user's session was explicitly terminated by some other means (e.g. an admin)
See issue #1198.
-
Added new overload of
IsRedirectUriValidAsync
toIRedirectUriValidator
that is passed an object containing additional contextual information. The context contains the requested uri, the client making the request, the complete request parameters, and, if the request parameters were sent as a signed request object, the claims from the validated request object.See issue #44.
-
Endpoint names are now public constants in
IdentityServerConstants.EndpointNames
, and the JWKS endpoint now has the unique nameIdentityServerConstants.EndpointNames.Jwks
. Referencing endpoints by name is useful when invoking endpoints programmatically, for example, from a health check. It also facilitates the creation of a customIEndpointRouter
. -
Added nullable reference type annotations to many public APIs.
See issue #749.
Logging Improvements
-
Data protection failures now log a more detailed message.
-
Back-channel logout error responses now include more details in their log messages.
See issue #1026.
-
Licensing log messages related to multiple issuers (commonly caused by misconfigured gateways) and automatic key management are now more descriptive.
-
Logs generated in the CIBA flow now have sensitive values scrubbed by the
BackchannelAuthenticationRequestSensitiveValuesFilter
option, which scrubsclient_secret
,client_assertion
, andid_token_hint
parameters from the logs. Previously these logs were filtered byTokenRequestSensitiveValuesFilter
, which did not includeid_token_hint
.See issue #1168.
-
Logs generated by the token endpoint now redact authorization codes from the raw request values that are logged. This is for consistency with the parsed value, which is logged as an obfuscated value. Previous logs that included codes should not be a concern, since codes are one time use only - by the time they are logged, they are not likely to be useful anymore.
See issue #1240.
Bug Fixes
-
Filtering sessions in the server side session quickstart UI uses the different filter fields properly
See issue #1111.
-
Requests to ~/federation with no additional segments returns not found instead of throwing an exception
See issue #1171.
-
Basic authorization header input length restrictions now account for base64-url encoding of client id and secret. The restrictions now apply to the length of those values before encoding.
See issue #1173.
-
Removed dependency on
IHttpContextAccessor
in several services, making it possible to use them when no there is no HTTP request, such as in a customized background job. The updated services areDefaultEventService
,PostConfigureApplicationCookieTicketStore
,ConfigureAuthenticationOptions
,OidcConfigureOptions
,CachingIdentityProviderStore
andNonCachingIdentityProviderStore
.See issue #874.