Upgrading from 11.4.X to 11.5.0#

Behavioral breaking changes#

The theme no longer uses the font weight variables#

The default theme ships the 2026 Curity brand in 11.5.0, whose font faces each declare their own weight, so the --type-weight and --type-weight-bold variables were removed. The stylesheets no longer read them and the Look and Feel page no longer offers them — see Settings and Theme for the current variables.

Theming through the Look and Feel page needs no action. Custom CSS that reads var(--type-weight) or var(--type-weight-bold) does: the declaration now resolves to nothing and that font-weight falls back to the inherited value, so state the weight directly instead.

Delegations are looked up strictly by tenant#

Every delegation data source we ship now resolves a delegation only when the delegation’s stored tenant matches the profile’s tenant. Previously the JDBC and DynamoDB data sources looked delegations up by id, and by authorization-code hash, without filtering on the tenant, while MongoDB already filtered by tenant. From 11.5.0, all three behave the same: a tenant mismatch is reported as not found rather than resolving a delegation that belongs to another tenant.

This closes a cross-tenant isolation gap, so the change is intentionally broad. By-id delegation access is the funnel for token introspection, the refresh-token grant, revocation, token exchange, userinfo, and the SCIM delegations endpoint; the authorization-code hash lookup is the authorization-code flow. All of them are now strictly scoped to the profile’s tenant.

The practical consequence is for delegations created on the JDBC data source before multi-tenancy support for delegations was added (9.4.0), whose tenant_id is NULL even though they logically belong to a tenant. After the upgrade a tenanted profile no longer resolves those legacy rows — they remain visible only to the default (untenanted) profile. No data is deleted; the rows simply stop matching a tenanted lookup.

This supersedes the guidance in the 9.3.X to 9.4.0 upgrade notes, which advised contacting Curity Support to associate existing delegations with their tenant. Those delegations predate multi-tenancy support for delegations (9.4.0, more than three years before 11.5.0) and are well beyond any realistic delegation lifetime, so they are intentionally not migrated. If you still need legacy NULL-tenant delegations to be resolvable by a tenanted profile, back-fill their tenant_id column to the owning tenant before upgrading.

Geolocation features deny a request from an unknown country#

Every geolocation feature that decides on the country of a request now treats a request from an unknown country as one that cannot satisfy a geographic condition. Before 11.5.0, each of these features let a request from an unknown country through in one of its two modes.

The country of a request is unknown when the address is one the geolocation database does not cover, such as a private or reserved range, when the address resolves without a country, or when the value received as the client address is not an address at all.

What changed, per feature:

  • Allow or Deny Country Action: a request from an unknown country is now denied in both modes. Before, it was denied only when the action was configured as an allow list, and allowed when configured as a deny list.
  • Geolocation Authenticator Filter: the exclusions are now applied to a request from an unknown country regardless of apply-filter-when-match. Before, they were applied only when apply-filter-when-match was false, and not when it was true, which is the default.
  • Geolocation settings on an authenticator: the authenticator is now blocked for a request from an unknown country regardless of allow-authenticator. Before, it was blocked only when allow-authenticator was true, and not when it was false, which is the default.
  • Changed Country and New Country actions: an authentication from an unknown country is now reported as a changed country and as a new country, and no country is recorded for it. Before, an unknown country was compared as though it were a country, so two authentications from two different unknown locations counted as being from the same country.

No data migration is needed.

Stricter validation of proof key challenge methods#

A code_challenge sent without a code_challenge_method is treated as plain, as defined by RFC 7636 (Proof Key for Code Exchange by OAuth Public Clients). If the profile disallows plain, clients must send code_challenge_method=S256 explicitly.

RESTCONF API group membership requires an exact name match#

When an administrator logs in without any groups, the groups that apply to them in the RESTCONF API, including the calls the Admin UI makes, are looked up by their name among the members of the NACM groups. That happens, for example, after a federated login whose ID token has no groups claim, or when a credential manager returns none of the groups used in access rules. Before 11.5.0, this lookup also matched a name that was only the beginning of a listed member: an administrator named adm was treated as a member of every group that lists admin. From 11.5.0, the name has to match a member exactly.

An administrator who received access this way loses it after the upgrade. To keep their access, add them to the NACM group under their own name.

A one-character administrator name, which the RESTCONF API used to reject, is now accepted.

JSON / REST Data Source - Attribute Data Access#

When a mapped parameter is sent in a JSON request body, the type of the attribute value is now preserved, including lists and maps/objects.

In previous versions, only primitive attribute values were considered and they were always converted to strings. For example, the value of a boolean attribute would be "true" or "false", instead of the actual JSON boolean value (true or false). In addition, list/map values were dropped. These were incorrect behaviors which have now been fixed.

An HTTP backend that depends on the incorrect behavior may need to be updated (e.g. deploy a new version in parallel to support the upgrade path).

Administrator and group names are encoded for the RESTCONF API#

Requests to the RESTCONF API, including the ones the Admin UI makes, identify the administrator and their groups to the configuration service through a text protocol that cannot carry every character. Before 11.5.0, some names were passed through as they were, so a name containing a space could be read as a shorter name or as several groups. From 11.5.0, user names and group names containing whitespace, control characters, |, ; or % are percent-encoded for those requests, and so is the first character of a group whose name is an integer. For example, john smith becomes john%20smith, ops%team becomes ops%25team and 1000 becomes %31000. Names without these characters are unchanged. The other management interfaces keep using names as they are. See Access Control for details.

Most deployments need no action. Review the NACM configuration if the names of administrators or of their groups contain any of the characters above:

  • Names containing %: such a user or group is now known to the RESTCONF API by its encoded name. If a NACM group lists the user, or a rule list names the group, update the entry to the encoded name, e.g. ops%25team.
  • Group names containing whitespace, such as the Active Directory group Domain Admins: such a group used to reach the RESTCONF API as two groups, Domain and Admins, so rules written for those fragments no longer apply. To grant RESTCONF access to the group, name it as Domain%20Admins in a rule list.
  • Group names that are integers: such a group was silently dropped, or caused the request to go unanswered. It is now a group like any other and must be named in its encoded form, e.g. %31000.
  • Group names containing |: a request from such an administrator used to fail with an internal error. The group is now encoded like any other.
  • Non-ASCII names: these used to reach the configuration service in the wrong encoding and could not match NACM entries for the RESTCONF API. They now do, so an administrator whose name or group is listed in NACM gets the access those entries grant.

The configuration service’s audit log records the encoded names. Update any log filters or alerts that match on the names of affected administrators.

Configuration breaking changes#

Introspection validates the token issuer#

Before 11.5.0, the token introspection endpoint did not check the issuer claim of a token. Two OAuth profiles that shared a signing key and a delegation data source could therefore introspect each other’s tokens. This allowed for some valid use cases, but could also cause surprises.

From 11.5.0, the introspecter validates the issuer by default. A token is reported as active only when its iss is one of the introspecting profile’s allowed issuers: the derived or overridden issuer plus every configured additional-issuer, as documented for the authorization-server settings. A token from another profile is now reported exactly like an unknown token ({"active": false}).

If a deployment relies on the previous, unvalidated behaviour, the check can be disabled with the following JVM system property:

-Dse.curity.introspection-ignore-token-issuer=true

Note that this property is JVM-wide: it disables the check for every OAuth profile on the node. It is intended only as a temporary escape hatch while affected deployments migrate, and is expected to be removed in a future release.

Token revocation is governed by the same check: the revocation endpoint resolves the presented token through the same introspection logic. In particular, after a profile’s issuer changes (for example via issuer-override) while tokens are outstanding, those tokens can no longer be revoked — just as they can no longer be introspected — until the previous issuer is listed as an additional-issuer. As required by RFC 7009, the revocation endpoint still responds with HTTP 200 in that case, but nothing is revoked; the denial is visible only as a DeniedRevocationOAuthEvent in the event log. The system property above also restores the previous revocation behaviour. Note that a token issued by a different profile was never revocable, in any version: reference-token lookups are scoped to the profile that issued the token.

SDK#

Kotlin upgrade#

The provided version of Kotlin was upgraded from 2.2.0 to 2.3.21. Plug-in developers are encouraged to upgrade to this version to remain aligned with the included version. We strongly recommend to recompile and thoroughly test all custom plugins written in Kotlin.

Ephemeral Clients - stricter Client ID Metadata Document validation#

Ephemeral clients were built against version 01 of the Client ID Metadata Document draft. Version 02 of that draft was published in July 2026, and 11.5.0 aligns the Curity Identity Server with it. As part of that alignment, the Curity Identity Server validates the URLs in a Client ID Metadata Document more strictly.

A root path is now valid in a client ID#

A client_id whose path is /, such as https://example.com/, is now accepted. The specification discourages it, because the metadata document then has to be served from the root of the domain where it can collide with content already published there, but it does not forbid it.

This only widens what the Curity Identity Server accepts, so no action is needed when upgrading.

The https scheme is enforced on more URLs#

Every URL in a Client ID Metadata Document other than redirect_uris must now use the https scheme. Whether a deployment is affected depends on its configuration:

  • logo_uri, policy_uri and tos_uri must use https even when informational-uris-same-origin is false.
  • jwks_uri must use https, even when jwks-uri-same-origin is false.
  • request_uris must use https. An http URL was previously accepted.

Special-use addresses are no longer fetched#

The specification requires that neither the client ID nor any URL the server dereferences from a Client ID Metadata Document resolves to a special-use address. the Curity Identity Server now enforces this on the client_id, jwks_uri and request_uris, rejecting private, loopback, link-local, shared, documentation and reserved ranges, along with host names that resolve to them.

Ephemeral clients hosted on such addresses stop working after the upgrade, including those reached over an internal network, a mesh or overlay VPN, or carrier-grade NAT. To keep them working, list their address ranges in the new allowed-address-ranges setting.

Credentials are no longer allowed in URLs#

A URL containing a userinfo component, such as https://user:password@example.com/logo.png, is now rejected in all fields containing URLs.

A published key set must contain public keys only#

Client ID Metadata Documents containing jwks or jwks_uri are now rejected if any key carries a private component, or if it is a symmetric key.

Serialization filter system property#

The se.curity:identity-server:serialFilter Java system property allows additional Java types to be deserialized, on top of the types the Curity Identity Server allows by default. In previous versions, setting this property did not work correctly: instead of only allowing the types matched by its patterns, it effectively disabled the restriction for every type not in the default allow-list. This was fixed in versions 11.4.3, 11.3.3, 11.2.4, 11.1.4, 11.0.6, 10.7.8, 10.6.6, 10.5.5, 10.4.7, 10.3.5, 10.2.6, 10.1.5 and 10.0.7.

From these versions, only the types matched by the property’s patterns are allowed in addition to the default ones, and any other type is rejected. Deployments that set this property must review its value and make sure that it matches every type that actually needs to be deserialized, as a value that is too narrow previously went unnoticed. A type rejected by the filter is logged as a warning (Type ... not allowed to be deserialized).

Oracle Database users are affected in particular: previous versions of this documentation recommended the value oracle.jdbc.**, which does not cover all types the Oracle driver deserializes. Change it to oracle.**, i.e. -Dse.curity:identity-server:serialFilter=oracle.**. See Oracle Driver and class serialization for details.

Was this helpful?