DATE:
AUTHOR:
Ory Team
Ory Network Ory Hydra Ory Kratos Ory Keto Ory Oathkeeper Ory Elements Ory Enterprise License

Ory Network, Ory Hydra, Ory Kratos, Ory Keto, Ory Oathkeeper, Ory Elements v26.3.4 released

DATE:
AUTHOR: Ory Team

Ory Network

Fix talos_secrets_hmac_retired serializing as null

The deprecated talos_secrets_hmac_retired field on normalized project revisions now serializes as an empty array ([]) instead of null when there are no retired HMAC secrets or when the secrets are redacted. This restores the array shape that older SDKs decode and matches the behavior of the retired issuer fields. The redacted talos_secrets_hmac_retired_entries field is also returned as an empty array rather than null. Secret values remain fully redacted.

Identity schemas deduplicate on creation

Creating an identity schema no longer stores duplicate copies of the same schema. Deduplication is based on the schema's content — the name is a display-only label and is not considered, matching how schemas are already resolved everywhere else (identities and the rendered configuration reference a schema by its content hash).

  • Importing a schema through a project configuration update (for example ory update identity-config, the Terraform provider, or any API call with a base64:// schema URL) now reuses the existing schema when one with identical content already exists. Repeated applies of the same configuration stay idempotent and no longer accumulate copies.

  • Creating a schema through the Ory Console API (POST /identity-schemas) now fails with 409 Conflict when you already have a schema with identical content, even under a different name. The response includes the existing schema's ID so you can reference it directly. The Ory Console surfaces the conflict and keeps your draft so you can adjust and retry.

Schemas with different content, or belonging to a different owner, are unaffected.

Override the Console session lifespan for organization SSO members

Workspace administrators can now override how long Console sessions last for members who sign in through their organization's SSO. Set a lifespan between 1 minute and 1 year from the workspace SSO settings, or reset it to the project default.


This is now available on Ory Network.


Ory Hydra

hydra update oauth2-client no longer resets fields you did not pass

The hydra update oauth2-client command now updates only the fields you provide as flags. Previously, the command replaced the entire client: any field not passed again on the command line was silently reset to its default value, which could drop redirect URIs, secrets-related settings, CORS origins, and other configuration.

The command now sends a partial update (PATCH /admin/clients/{id}) built from exactly the flags you set. For example, running hydra update oauth2-client <id> --name "new name" changes only the client name and leaves all other settings untouched.

Updating from a file (--file client.json or --file -) keeps the previous behavior and replaces the entire client, since a file represents a complete client configuration.

Breaking changes

Scripts that relied on hydra update oauth2-client resetting unspecified fields to their defaults must now pass a complete client definition with --file to get replace semantics.

Ory CLI

The equivalent change in the Ory CLI (ory update oauth2-client) will land in CLI v1.3.2.

Faster OAuth2 token issuance under database latency

Ory Hydra no longer serializes JSON Web Key reads behind a global lock. Token issuance, the authorize flow, and the OpenID Connect discovery endpoint now read signing keys concurrently, so a slow database query no longer queues all other requests behind it.

Generating a missing key set is now deduplicated per network and key set: concurrent requests that race on a fresh installation trigger exactly one key generation per instance and share its result. A request that is canceled while waiting no longer aborts the generation for other waiting requests.

The Ory Hydra OEL key-set cache now scopes cache entries by network ID.

Fix OIDC session leak in the device authorization grant

The OpenID Connect device grant now deletes its stored OIDC session after issuing an id_token. Previously the session was looked up by the device-code signature but deleted using the raw device_code, so the delete never matched and every successful device-flow id_token issuance left one OIDC session behind. On storage backends without a TTL this grew without bound.

This is an availability fix only. Device codes could still not be replayed, so there was no token-reuse or authorization impact.

Hydra CLI reports the key set name when getting JSON Web Keys

hydra get jwks (and ory get jwk in the Ory CLI) now reports which key set each key belongs to. Previously the set attribute was missing from JSON and YAML output for single-key sets, and empty in every output format for sets with more than one key.

Each key in the output now carries its own set attribute. When keys from several sets are fetched in one command, the keys are attributed to their correct sets instead of an empty name.

The API reference for creating a JSON Web Key now documents that generating a key into an existing set keeps the existing keys, except on deployments using a Hardware Security Module (HSM), where the set is replaced and contains only the new key.

Metrics endpoints now support OpenMetrics and trace exemplars

The Prometheus metrics endpoints of Kratos, Keto, Hydra, Oathkeeper, and Talos now additionally serve the OpenMetrics exposition format. The format is selected automatically through standard HTTP content negotiation: scrapers that ask for OpenMetrics receive it, and all other scrapers keep receiving the classic text format. No configuration or scraper change is necessary.

OpenMetrics enables exemplars, which attach a trace reference to a metric sample. Two sets of metrics use this:

  • The HTTP request duration histograms and request counters attach an exemplar when a request runs under a sampled trace, so latency dashboards can link slow-request outliers and error spikes to the traces that caused them.

  • The ory_x_popx_cockroach_transaction_retries_total counter attaches an exemplar whose value is the transaction's retry count when a transaction is retried during a traced request, and the trace records a db.transaction.retry span event. Dashboards can link retry spikes directly to the traces that caused them.

That counter's caller label now also more reliably attributes automatic CockroachDB transaction retries to the business operation that opened the transaction, for example the OAuth2 refresh token flow, instead of a generic persistence Transaction wrapper method. This makes it possible to see which operation is causing database contention. Dashboards or alerts that match specific caller label values may need updating, because existing label values change with this release.

OAuth2 client secret rotation

Hydra now supports zero-downtime client secret rotation. See the documentation for details.

Thanks to @SamuelDev (https://github.com/SamuelDev) for the initial implementation!

YugabyteDB support for Kratos, Hydra, and Keto (OEL)

Ory Enterprise License deployments can now run Ory Kratos, Ory Hydra, and Ory Keto against YugabyteDB.

Enabling YugabyteDB

Point the dsn at your YugabyteDB cluster using the yugabyte:// scheme (the synonym yugabytedb:// also works):

yugabyte://user@host:5433/database?sslmode=disable

Recovering an interrupted migration

YugabyteDB applies DDL with autocommit. Old PostgreSQL migrations inherited by YugabyteDB can contain multiple statements, so an interruption may leave the first statements applied without a row in schema_migration. Current versions of Ory no longer use multi-statement migrations and are safe.


This is now available on Ory Network, for the Ory Enterprise License, and will be part of the next Ory Open Source release.


Ory Kratos

Account linking now works when registration is disabled

Automatic account linking now works when registration is disabled. Signing in with an OIDC or SAML provider whose email matches an existing account starts the account linking flow even if selfservice.flows.registration.enabled is false. New sign-ups remain blocked. Previously, the linking attempt failed with "Registration is not allowed because it was disabled."

Bound the password identifier-similarity check by length

The password validator's identifier-similarity check now bounds the length of the identifier and password it compares. Real identifiers and passwords are far shorter than this bound, so legitimate flows are unaffected. This hardens the check against excessive resource use on very long inputs.

Exclude already registered credentials in WebAuthn and passkey settings

The WebAuthn and passkey settings flows now populate excludeCredentials in the registration challenge with the identity's already registered credentials. Browsers no longer silently overwrite an existing platform-authenticator entry (Touch ID, Windows Hello, Android) when a user re-enrolls the same device; instead the authenticator reports the credential as already registered. Kratos additionally rejects a registration response whose credential ID is already registered on the identity.

Metrics endpoints now support OpenMetrics and trace exemplars

The Prometheus metrics endpoints of Kratos, Keto, Hydra, Oathkeeper, and Talos now additionally serve the OpenMetrics exposition format. The format is selected automatically through standard HTTP content negotiation: scrapers that ask for OpenMetrics receive it, and all other scrapers keep receiving the classic text format. No configuration or scraper change is necessary.

OpenMetrics enables exemplars, which attach a trace reference to a metric sample. Two sets of metrics use this:

  • The HTTP request duration histograms and request counters attach an exemplar when a request runs under a sampled trace, so latency dashboards can link slow-request outliers and error spikes to the traces that caused them.

  • The ory_x_popx_cockroach_transaction_retries_total counter attaches an exemplar whose value is the transaction's retry count when a transaction is retried during a traced request, and the trace records a db.transaction.retry span event. Dashboards can link retry spikes directly to the traces that caused them.

That counter's caller label now also more reliably attributes automatic CockroachDB transaction retries to the business operation that opened the transaction, for example the OAuth2 refresh token flow, instead of a generic persistence Transaction wrapper method. This makes it possible to see which operation is causing database contention. Dashboards or alerts that match specific caller label values may need updating, because existing label values change with this release.

Opt-in cleanup of expired data on CockroachDB

Ory Kratos Enterprise License deployments on CockroachDB can now set up row-level TTL jobs that automatically delete expired data. Run the new kratos migrate row-ttl up command to configure these retention periods:

  • Self-service flows, one-time codes, tokens, and continuity containers: 7 days after they expire.

  • Sessions: 30 days after they expire.

  • Courier messages, message dispatches, and self-service errors: 30 days after they are created.

The command is opt-in: kratos migrate sql up does not change TTL settings. Use kratos migrate row-ttl dump to print the SQL statements — for review, or to adapt the retention periods and apply them manually. kratos migrate row-ttl status shows which TTL migrations are applied, and kratos migrate row-ttl down removes the TTL configuration again.

Running kratos migrate row-ttl up replaces any custom row-level TTL settings on the affected tables with the defaults above. The command requires CockroachDB and exits with an error on other databases.

CockroachDB deletes expired rows on a schedule, not at the exact moment the retention period ends. Expired rows can remain in the database for some time: either the TTL job has not processed them yet, or it has deleted them but garbage collection has not yet removed them.

Persist WebAuthn and passkey sign counter for clone detection

Ory now updates the stored WebAuthn and passkey authenticator state after every successful login. The signature counter, clone-warning flag, and backup state are written back to the credential, so W3C WebAuthn clone detection works as intended.

Previously the signature counter stayed at its registration value, which left clone detection inert. A login that presents a non-increasing counter is still allowed — synced passkeys (such as Apple iCloud or Google) legitimately report a static counter — but the possible-clone warning is now recorded on the credential and is visible through the admin identity API.

Revoke a single DeviceAuthn key by identifier

DELETE /admin/identities/{id}/credentials/deviceauthn now revokes a single DeviceAuthn key selected by the identifier query parameter, where the identifier is the key's client_key_id. This is the same parameter that OIDC and SAML credential deletion already use.

Because the client_key_id is unique per identity, administrators can revoke exactly one device key without affecting other keys — including keys that share the same device name. Before, deleting the deviceauthn credential type removed all device keys at once.

The endpoint returns 404 Not Found when the identity has no deviceauthn credential or when no key matches the identifier, and 400 Bad Request when the identifier is missing. Removing the last key leaves the deviceauthn credential with no keys.

Find the client key ids by calling GET /admin/identities/{id}?include_credential=deviceauthn.

Second-factor enrollment now refreshes the session's authenticated_at timestamp

Setting up a second factor — authenticator app (TOTP), security key, passkey, or lookup secret — in a settings flow now refreshes the session's authenticated_at timestamp, in addition to elevating the session to AAL2. Linking a social sign-in provider in a settings flow also refreshes the timestamp.

Previously, enrolling a second factor raised the session to AAL2 but left authenticated_at unchanged. Because AAL2 re-authentication prompts are timed from authenticated_at, users could be asked to re-authenticate immediately after proving possession of the factor they had just enrolled. The timestamp now reflects the enrollment as the most recent authentication event.

Support non-RFC email addresses end-to-end when the identity schema allows them

Identity schemas can use format: no-validate with a custom pattern to accept non-RFC email addresses — for example Japanese carrier addresses such as [email protected], which carry a leading, trailing, or consecutive dot in the local part. Previously these addresses were accepted at registration by the schema pattern but then rejected by stricter per-flow checks, so affected users could not verify, recover, or sign in with a one-time code.

These addresses now work consistently across registration, verification, passwordless code login, and account recovery:

  • The passwordless-code and recovery identity-schema extensions honor the trait's format and pattern instead of applying a strict RFC check.

  • Account recovery and verification accept these addresses at submission time.

  • The courier delivers email to these addresses instead of failing to queue or send.

Email recipient and submission validation remain injection-safe: they reject empty or over-long values, control characters, whitespace, and the characters that are unsafe in an email header or SMTP envelope, and they require the domain to be a valid host name. The courier re-checks the recipient at delivery time, and invalid entries still show the same "Enter a valid email address" message.

YugabyteDB support for Kratos, Hydra, and Keto (OEL)

Ory Enterprise License deployments can now run Ory Kratos, Ory Hydra, and Ory Keto against YugabyteDB.

Enabling YugabyteDB

Point the dsn at your YugabyteDB cluster using the yugabyte:// scheme (the synonym yugabytedb:// also works):

yugabyte://user@host:5433/database?sslmode=disable

Recovering an interrupted migration

YugabyteDB applies DDL with autocommit. Old PostgreSQL migrations inherited by YugabyteDB can contain multiple statements, so an interruption may leave the first statements applied without a row in schema_migration. Current versions of Ory no longer use multi-statement migrations and are safe.


This is now available on Ory Network, for the Ory Enterprise License, and will be part of the next Ory Open Source release.


Ory Keto

Metrics endpoints now support OpenMetrics and trace exemplars

The Prometheus metrics endpoints of Kratos, Keto, Hydra, Oathkeeper, and Talos now additionally serve the OpenMetrics exposition format. The format is selected automatically through standard HTTP content negotiation: scrapers that ask for OpenMetrics receive it, and all other scrapers keep receiving the classic text format. No configuration or scraper change is necessary.

OpenMetrics enables exemplars, which attach a trace reference to a metric sample. Two sets of metrics use this:

  • The HTTP request duration histograms and request counters attach an exemplar when a request runs under a sampled trace, so latency dashboards can link slow-request outliers and error spikes to the traces that caused them.

  • The ory_x_popx_cockroach_transaction_retries_total counter attaches an exemplar whose value is the transaction's retry count when a transaction is retried during a traced request, and the trace records a db.transaction.retry span event. Dashboards can link retry spikes directly to the traces that caused them.

That counter's caller label now also more reliably attributes automatic CockroachDB transaction retries to the business operation that opened the transaction, for example the OAuth2 refresh token flow, instead of a generic persistence Transaction wrapper method. This makes it possible to see which operation is causing database contention. Dashboards or alerts that match specific caller label values may need updating, because existing label values change with this release.

YugabyteDB support for Kratos, Hydra, and Keto (OEL)

Ory Enterprise License deployments can now run Ory Kratos, Ory Hydra, and Ory Keto against YugabyteDB.

Enabling YugabyteDB

Point the dsn at your YugabyteDB cluster using the yugabyte:// scheme (the synonym yugabytedb:// also works):

yugabyte://user@host:5433/database?sslmode=disable

Recovering an interrupted migration

YugabyteDB applies DDL with autocommit. Old PostgreSQL migrations inherited by YugabyteDB can contain multiple statements, so an interruption may leave the first statements applied without a row in schema_migration. Current versions of Ory no longer use multi-statement migrations and are safe.


This is now available for the Ory Enterprise License and will be part of the next Ory Open Source release.


Ory Oathkeeper

Metrics endpoints now support OpenMetrics and trace exemplars

The Prometheus metrics endpoints of Kratos, Keto, Hydra, Oathkeeper, and Talos now additionally serve the OpenMetrics exposition format. The format is selected automatically through standard HTTP content negotiation: scrapers that ask for OpenMetrics receive it, and all other scrapers keep receiving the classic text format. No configuration or scraper change is necessary.

OpenMetrics enables exemplars, which attach a trace reference to a metric sample. Two sets of metrics use this:

  • The HTTP request duration histograms and request counters attach an exemplar when a request runs under a sampled trace, so latency dashboards can link slow-request outliers and error spikes to the traces that caused them.

  • The ory_x_popx_cockroach_transaction_retries_total counter attaches an exemplar whose value is the transaction's retry count when a transaction is retried during a traced request, and the trace records a db.transaction.retry span event. Dashboards can link retry spikes directly to the traces that caused them.

That counter's caller label now also more reliably attributes automatic CockroachDB transaction retries to the business operation that opened the transaction, for example the OAuth2 refresh token flow, instead of a generic persistence Transaction wrapper method. This makes it possible to see which operation is causing database contention. Dashboards or alerts that match specific caller label values may need updating, because existing label values change with this release.


This is now available for the Ory Enterprise License and will be part of the next Ory Open Source release.


Ory Elements

Login no longer shows a single-option method chooser when passkey autofill is enabled

The two-step login card now skips the "choose a method" screen when only one authentication method is actually selectable. Previously, an identity with a password credential and passkey autofill (conditional UI) enabled was shown a method chooser with password as the only option, because the passkey group's hidden helper fields were counted as a selectable method. The same rule now also hides the "Choose another method" link when there is no other visible method to choose. Flows that offer SSO providers keep the chooser and the link, because SSO buttons render on the chooser screen.

One-time-code screens now use SMS wording for phone identifiers

Account Experience one-time-code screens now detect whether the code is delivered by SMS or email. When the code goes to a phone number, the authentication method picker shows "A verification code will be sent to your phone" with a phone icon, the second-factor login screen announces the code is sent by SMS, and the verification screen uses the phone-specific message and an "email address or phone number" prompt. Previously these screens always claimed the code was sent by email. Email-based codes keep their existing wording. The new texts are translated in all supported languages.


This is now available on Ory Network and will be part of the next Ory Open Source release.


Ory Polis and Ory Terraform

No significant changes in this release.

Powered by LaunchNotes