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 whenapply-filter-when-matchwasfalse, and not when it wastrue, 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 whenallow-authenticatorwastrue, and not when it wasfalse, 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,DomainandAdmins, so rules written for those fragments no longer apply. To grant RESTCONF access to the group, name it asDomain%20Adminsin 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_uriandtos_urimust usehttpseven wheninformational-uris-same-originisfalse.jwks_urimust usehttps, even whenjwks-uri-same-originisfalse.request_urismust usehttps. AnhttpURL 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.