- DATE:
- AUTHOR:
- Ory Team
Ory Network, Ory Hydra, Ory Kratos, Ory Keto, Ory Oathkeeper, Ory Polis v26.3.15 released
Ory Network
Set technical, business, security, and privacy contacts for a workspace
You can now register who Ory should reach for each workspace. Open the workspace settings in the Ory Console and add a contact for one or more of the technical, business, security, and privacy responsibilities. A contact is either a current workspace member or an email address, and one contact can hold several responsibilities.
Once a contact is set, Ory sends communication for that topic to that address. For example, security notices go to the security contact and privacy or data processing updates go to the privacy contact. Workspaces without contacts keep receiving communication as before.
All workspace members can view contacts. Only members who can manage workspace settings can add, change, or remove them. Being a contact grants no Console permissions, and removing a member also removes that member's contacts from the workspace.
This is now available on Ory Network.
Ory Hydra
Oathkeeper adopts shared HTTP metrics and adds per-rule access decisions
Oathkeeper uses the shared Ory HTTP metric schema. It also exposes
ory_oathkeeper_access_decisions_total, which reports allowed requests,
authentication failures, authorization failures, and pipeline errors by rule ID.
Access decisions are independent of login redirects and upstream response codes.
Breaking changes
For Oathkeeper dashboards and alerts, replace service with app and
status_code with code. The request label is replaced by endpoint, which
contains API router patterns such as /rules/{param} and /decisions/ and is
empty for proxy traffic. The app values remain oathkeeper-api and
oathkeeper-proxy. HTTP metrics also include version, hash, and
buildTime. Metric names retain the configured prefix. Health requests are now
included.
serve.prometheus.hide_request_paths and
serve.prometheus.collapse_request_paths are deprecated and have no effect.
Update path filters to use router patterns or the new per-rule counter.
In Oathkeeper, Kratos, Hydra, and Keto, the requests_statuses_total metric's
method labels now follow the same normalization as other shared HTTP metrics:
recognized methods use lowercase values, and other methods use other.
Oathkeeper applies this normalization to all HTTP metrics.
Unsupported methods use other instead of unknown across all shared HTTP
metrics. Update queries that filter on the previous method label.
Require user authorization for verifiable credentials
POST /credentials issues credentials only to access tokens that represent an
authenticated end user and carry both the openid and
userinfo_credential_draft_00 scopes. The same requirement applies to nonce
priming requests. Both scopes must be granted explicitly; a wildcard grant does
not satisfy the requirement.
Breaking changes
A token that does not carry both scopes receives scope_not_granted with
HTTP 403. Scope names are matched exactly, so a scope that differs in case does
not satisfy the requirement.
To use this draft endpoint, request both scopes in the authorization flow and
grant both during consent. The token endpoint returns c_nonce_draft_00 only
for tokens that meet these requirements. Other access token issuance is
unaffected.
Device authorization errors are shown on the error page
An OAuth 2.0 device authorization grant has no redirect URI, so an error at the device verification endpoint had nowhere to go and was written to the browser as a JSON response body. The most common case is a user who denies the request at the login or consent screen: they were left looking at raw JSON.
Those errors are now sent to the error page configured under urls.error,
carried in the error and error_description query parameters, the same way an
authorization request that has no valid redirect URI already is. A denial
arrives there under the error code the rejection named, and the device still
receives access_denied on its next poll.
If your error page distinguishes the errors it receives, expect device
verification errors on it now. GET /oauth2/device/verify no longer answers any
error with a JSON body: every error path redirects to the error page instead.
The device polling behavior is unchanged.
A rejection also reads as one sentence now. Account Experience rejects a login
or consent request with error_description set to "The request was rejected.
The application was not granted access to your account." and no longer sends
error_hint, so OAuth 2.0 clients of a redirect-based flow receive that text in
their error redirect.
Hydra gains a FIPS 140-3 build
Ory Enterprise License releases now include a dedicated FIPS build of Hydra
(hydra_oel_fips_<version>_<os>_<arch>) next to the standard build. The FIPS
build uses the Go Cryptographic Module and starts with GODEBUG=fips140=on by
default, so Hydra's cryptography runs through the FIPS 140-3 validated module.
The standard build is unchanged as long as it runs without
GODEBUG=fips140=on.
A few things need attention before you switch. The FIPS build seals transient
payloads with AES-256-GCM instead of XChaCha20-Poly1305, so the two builds
cannot read each other's login, consent, device, and logout flows, verifiable
credential nonces, unredeemed authorization codes, or admin API page tokens;
plan a stop-then-start cutover. hydra serve refuses to start unless
secrets.system, secrets.cookie, and secrets.pagination are each set
explicitly with their own active secret, and unless oauth2.hashers.algorithm
is pbkdf2 — bcrypt hashes client secrets outside the validated module,
though client secrets already hashed with it keep verifying. And because
AES-GCM draws a random nonce per payload, regular rotation of secrets.system
is mandatory in FIPS mode.
For the full picture — obtaining and verifying the build, the required configuration, the rotation budget, and what each cipher changes to — see FIPS 140-3 build.
TLS configuration and unix socket recovery in Hydra, Keto and Kratos
A configured certificate is now the only switch for TLS in all three services.
serve.<endpoint>.tls.enabled is deprecated but still accepted so that an
existing configuration keeps loading, but it has no effect. Each service logs a
warning at startup naming the key to remove. To serve plain HTTP behind a proxy
that terminates TLS, remove the certificate rather than the flag.
Hydra and Kratos also pick up two fixes from the shared serve configuration:
configuring only one half of a certificate pair is now a startup error instead of a listener that silently falls back to plain HTTP
a unix socket left behind by an unclean shutdown is replaced instead of blocking the next start.
Because the three services now configure their endpoints identically, the documentation for it is one page: Serving the APIs. It replaces the separate Hydra and Kratos HTTPS pages, which now redirect to it.
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
Oathkeeper adopts shared HTTP metrics and adds per-rule access decisions
Oathkeeper uses the shared Ory HTTP metric schema. It also exposes
ory_oathkeeper_access_decisions_total, which reports allowed requests,
authentication failures, authorization failures, and pipeline errors by rule ID.
Access decisions are independent of login redirects and upstream response codes.
Breaking changes
For Oathkeeper dashboards and alerts, replace service with app and
status_code with code. The request label is replaced by endpoint, which
contains API router patterns such as /rules/{param} and /decisions/ and is
empty for proxy traffic. The app values remain oathkeeper-api and
oathkeeper-proxy. HTTP metrics also include version, hash, and
buildTime. Metric names retain the configured prefix. Health requests are now
included.
serve.prometheus.hide_request_paths and
serve.prometheus.collapse_request_paths are deprecated and have no effect.
Update path filters to use router patterns or the new per-rule counter.
In Oathkeeper, Kratos, Hydra, and Keto, the requests_statuses_total metric's
method labels now follow the same normalization as other shared HTTP metrics:
recognized methods use lowercase values, and other methods use other.
Oathkeeper applies this normalization to all HTTP metrics.
Unsupported methods use other instead of unknown across all shared HTTP
metrics. Update queries that filter on the previous method label.
Sensitive values are now encrypted by default
Kratos used to default to the no-op cipher, which stored sensitive values in
plaintext — OIDC provider tokens, and DeviceAuthn PIN secrets in Ory Enterprise
License deployments. ciphers.algorithm now defaults to
[xchacha20-poly1305, noop]: new values are encrypted with XChaCha20 Poly1305,
and values already stored in plaintext keep decrypting until they are written
again. An unknown algorithm no longer falls back to plaintext; it fails closed,
and every encrypt or decrypt returns an error.
Breaking changes
secrets.cipher is now required. Kratos refuses to start unless it holds at
least one 32-character secret. Add it to your configuration before you upgrade —
the current version accepts the setting and ignores it, so the rollout is:
Add a 32-character
secrets.cipher.Roll out this version.
To keep storing these values in plaintext, set ciphers.algorithm: noop
explicitly. This provides no confidentiality or integrity and is not
recommended. secrets.cipher is required either way.
During the rolling upgrade, instances still running the previous version can't
read values that upgraded instances have already encrypted. If you can't
tolerate that window, set ciphers.algorithm: noop explicitly in step 1 and
remove it once every instance runs the new version. Both instances then agree on
the algorithm throughout the rollout, and the switch happens on a configuration
change rather than across the deployment.
Changing the algorithm
ciphers.algorithm also accepts an ordered list. The first algorithm encrypts
new values; the rest only decrypt older ones, and each value is re-encrypted
with the first algorithm on its next write. This mirrors secrets.cipher key
rotation, one level up, so you can change algorithms without re-encrypting
existing data and without downtime. noop is only valid as the last entry,
because it decodes any value and would shadow the algorithms after it.
Import identities faster with all-or-nothing batches
PATCH /admin/identities accepts a new with_partial_inserts field in the
request body. It defaults to true, which is the existing behavior: each
identity is imported on its own, and an identity that conflicts with one that
already exists is reported individually while the rest of the batch is still
imported.
Set it to false to import the batch as a single unit. The whole batch is then
written in one transaction, which is considerably faster. In a cluster
whose regions are 250 ms apart, a batch of 10 identities that took 2.2 seconds
takes 0.4 seconds, and a batch of 1000 that took 7 seconds takes 2.5. In
exchange, a single conflict fails the request with 409 Conflict and no
identity from the batch is created.
Use it when you expect the batch to contain no duplicates. That is the case when
you import from a database that already enforces the same unique constraints, or
when you have validated the data beforehand. You can also use it optimistically:
send the batch with with_partial_inserts set to false, and repeat the request
with true if it returns 409 Conflict.
The response does not say which identities conflicted, because none of them were
imported. The retry with with_partial_inserts set to true imports every
identity that does not conflict and reports a per-identity error for the ones
that do.
Support IdP-initiated SAML login
Enterprise users can now start a login from their identity provider's app launcher (for example the Okta or Azure AD dashboard) and land in your application with a valid Ory session.
When an identity provider posts an unsolicited SAML response, Ory Polis
validates it and redirects the browser to a new Kratos entry point with a
single-use authorization code. Kratos starts a regular SP-initiated login flow —
with the usual state, CSRF, and PKCE protections — and forwards the code as a
code_hint to the Polis authorize endpoint. Polis consumes the hint and
completes the flow immediately, without a second round-trip to the identity
provider.
Standalone Ory Polis already supports IdP-initiated SAML login through its
direct redemption flow. This change adds the Kratos side: an entry point that
folds the unsolicited response into a regular SP-initiated Kratos login, wired
together with Polis through the code_hint.
To enable it on Ory Network, turn on the "IdP-initiated login" toggle in the SAML provider settings in Ory Console. Ory then points the SAML connection's default redirect URL at the entry point automatically.
To enable it on a self-hosted Ory deployment that runs Kratos and Polis together:
Set
idp_initiated_login_enabled: trueon the SAML (jackson) provider in your Kratos configuration.Point the Polis SAML connection's
defaultRedirectUrlathttps://<your-project>/self-service/methods/saml/idp-initiated/<provider>.Run Polis with
IDP_ENABLED=true.
IDP_ENABLED is the deployment-wide switch. A connection follows it unless it
sets idpInitiatedLoginEnabled explicitly: true always allows IdP-initiated
login for that connection and false always blocks it. On Ory Network the
switch stays off and the Console toggle sets the per-connection flag, so no
deployment-wide change is needed.
The code hint is single use, expires with the code store TTL, and is only valid for the exact connection it was issued for. SP-initiated codes cannot be used as hints. If a hint is invalid or already consumed, the user is sent through the regular SP-initiated redirect instead — usually completing silently against the identity provider's existing session.
TLS configuration and unix socket recovery in Hydra, Keto and Kratos
A configured certificate is now the only switch for TLS in all three services.
serve.<endpoint>.tls.enabled is deprecated but still accepted so that an
existing configuration keeps loading, but it has no effect. Each service logs a
warning at startup naming the key to remove. To serve plain HTTP behind a proxy
that terminates TLS, remove the certificate rather than the flag.
Hydra and Kratos also pick up two fixes from the shared serve configuration:
configuring only one half of a certificate pair is now a startup error instead of a listener that silently falls back to plain HTTP
a unix socket left behind by an unclean shutdown is replaced instead of blocking the next start.
Because the three services now configure their endpoints identically, the documentation for it is one page: Serving the APIs. It replaces the separate Hydra and Kratos HTTPS pages, which now redirect to it.
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
Oathkeeper adopts shared HTTP metrics and adds per-rule access decisions
Oathkeeper uses the shared Ory HTTP metric schema. It also exposes
ory_oathkeeper_access_decisions_total, which reports allowed requests,
authentication failures, authorization failures, and pipeline errors by rule ID.
Access decisions are independent of login redirects and upstream response codes.
Breaking changes
For Oathkeeper dashboards and alerts, replace service with app and
status_code with code. The request label is replaced by endpoint, which
contains API router patterns such as /rules/{param} and /decisions/ and is
empty for proxy traffic. The app values remain oathkeeper-api and
oathkeeper-proxy. HTTP metrics also include version, hash, and
buildTime. Metric names retain the configured prefix. Health requests are now
included.
serve.prometheus.hide_request_paths and
serve.prometheus.collapse_request_paths are deprecated and have no effect.
Update path filters to use router patterns or the new per-rule counter.
In Oathkeeper, Kratos, Hydra, and Keto, the requests_statuses_total metric's
method labels now follow the same normalization as other shared HTTP metrics:
recognized methods use lowercase values, and other methods use other.
Oathkeeper applies this normalization to all HTTP metrics.
Unsupported methods use other instead of unknown across all shared HTTP
metrics. Update queries that filter on the previous method label.
Keto can serve its APIs over HTTPS
Every Keto endpoint - read, write, OPL syntax and metrics - can now terminate TLS itself. Point Keto at a certificate and key, either as file paths or as base64-encoded PEM:
serve:
read:
tls:
cert:
path: /etc/keto/tls/tls.crt
key:
path: /etc/keto/tls/tls.keyConfiguring a certificate is what turns TLS on for an endpoint. If the TLS configuration is incomplete or incorrect, Keto fails to start instead of silently falling back to insecure HTTP.
When you configure the certificate through path, Keto reloads it automatically
as it changes on disk, so certificate rotation needs no restart. gRPC and HTTP
clients keep working over the TLS port.
TLS is off by default and the listen addresses are unchanged, so existing deployments continue to serve plain HTTP.
Listening on a unix socket
Every endpoint can also listen on a unix socket instead of a TCP port. Set the
host to a unix: path and control who may connect through the file permissions:
serve:
read:
host: unix:/var/run/keto/read.sock
socket:
owner: keto
group: keto
mode: 384 # 0600Connecting to a unix socket requires write permission on the socket file, so
mode is the access control for the endpoint. It defaults to 493 (0755),
which lets only the owner connect. Keto removes the socket file when it shuts
down.
A unix socket endpoint cannot terminate TLS, because the socket permissions are the access control and there is no host name for a client to verify. Configuring both is rejected at startup rather than silently serving one of them.
Configuration that is now rejected
Two configurations that Keto used to accept and silently ignore are now rejected
at startup: a write_listen_file without the file:// scheme, and a tls.cert
or tls.key that sets both path and base64. Neither ever took effect, so
correct the value and Keto starts as before.
TLS configuration and unix socket recovery in Hydra, Keto and Kratos
A configured certificate is now the only switch for TLS in all three services.
serve.<endpoint>.tls.enabled is deprecated but still accepted so that an
existing configuration keeps loading, but it has no effect. Each service logs a
warning at startup naming the key to remove. To serve plain HTTP behind a proxy
that terminates TLS, remove the certificate rather than the flag.
Hydra and Kratos also pick up two fixes from the shared serve configuration:
configuring only one half of a certificate pair is now a startup error instead of a listener that silently falls back to plain HTTP
a unix socket left behind by an unclean shutdown is replaced instead of blocking the next start.
Because the three services now configure their endpoints identically, the documentation for it is one page: Serving the APIs. It replaces the separate Hydra and Kratos HTTPS pages, which now redirect to it.
This is now available for the Ory Enterprise License and will be part of the next Ory Open Source release.
Ory Oathkeeper
Oathkeeper adopts shared HTTP metrics and adds per-rule access decisions
Oathkeeper uses the shared Ory HTTP metric schema. It also exposes
ory_oathkeeper_access_decisions_total, which reports allowed requests,
authentication failures, authorization failures, and pipeline errors by rule ID.
Access decisions are independent of login redirects and upstream response codes.
Breaking changes
For Oathkeeper dashboards and alerts, replace service with app and
status_code with code. The request label is replaced by endpoint, which
contains API router patterns such as /rules/{param} and /decisions/ and is
empty for proxy traffic. The app values remain oathkeeper-api and
oathkeeper-proxy. HTTP metrics also include version, hash, and
buildTime. Metric names retain the configured prefix. Health requests are now
included.
serve.prometheus.hide_request_paths and
serve.prometheus.collapse_request_paths are deprecated and have no effect.
Update path filters to use router patterns or the new per-rule counter.
In Oathkeeper, Kratos, Hydra, and Keto, the requests_statuses_total metric's
method labels now follow the same normalization as other shared HTTP metrics:
recognized methods use lowercase values, and other methods use other.
Oathkeeper applies this normalization to all HTTP metrics.
Unsupported methods use other instead of unknown across all shared HTTP
metrics. Update queries that filter on the previous method label.
This is now available for the Ory Enterprise License and will be part of the next Ory Open Source release.
Ory Polis
DynamoDB deployments now honor the page limit when listing records
When DB_ENGINE is dynamodb, endpoints that list records by an index returned
every matching record in one response and ignored the requested page size. They
now return at most DB_PAGE_LIMIT records per call, which matches every other
database engine.
DynamoDB cannot skip records, so pageOffset is ignored on this engine. When
you page through connections, directory users or groups, or SSO traces with the
management API, read the pageToken from the response and pass it back to fetch
the next page.
SCIM is the exception, because it has no page token. The SCIM endpoints an
identity provider calls page with startIndex, which DynamoDB ignores, so on
this engine an identity provider reads the first DB_PAGE_LIMIT users or groups
of a directory and cannot reach the rest. Do not run directory sync on DynamoDB
with directories larger than DB_PAGE_LIMIT.
Index rows are also written in batches now, and any row DynamoDB reports as unwritten is retried. Under heavy write throttling a record could previously be saved but stay unreachable through one of the indexes that point at it.
Listing SSO connections now returns all of them
Reading the SSO connections for a tenant and product returned only as many as a
single database read yields, which DB_PAGE_LIMIT caps and defaults to 50. A
tenant with more connections than that saw a short list with nothing to indicate
records were missing, and the same limit applied when reading connections for
several tenants at once, when filtering by strategy, and when looking up
connections by identity provider entity ID.
All of these now read through to the end of the list. If you have more
connections than DB_PAGE_LIMIT under one tenant and product, expect the list
to be longer than before.
Support IdP-initiated SAML login
Enterprise users can now start a login from their identity provider's app launcher (for example the Okta or Azure AD dashboard) and land in your application with a valid Ory session.
When an identity provider posts an unsolicited SAML response, Ory Polis
validates it and redirects the browser to a new Kratos entry point with a
single-use authorization code. Kratos starts a regular SP-initiated login flow —
with the usual state, CSRF, and PKCE protections — and forwards the code as a
code_hint to the Polis authorize endpoint. Polis consumes the hint and
completes the flow immediately, without a second round-trip to the identity
provider.
Standalone Ory Polis already supports IdP-initiated SAML login through its
direct redemption flow. This change adds the Kratos side: an entry point that
folds the unsolicited response into a regular SP-initiated Kratos login, wired
together with Polis through the code_hint.
To enable it on Ory Network, turn on the "IdP-initiated login" toggle in the SAML provider settings in Ory Console. Ory then points the SAML connection's default redirect URL at the entry point automatically.
To enable it on a self-hosted Ory deployment that runs Kratos and Polis together:
Set
idp_initiated_login_enabled: trueon the SAML (jackson) provider in your Kratos configuration.Point the Polis SAML connection's
defaultRedirectUrlathttps://<your-project>/self-service/methods/saml/idp-initiated/<provider>.Run Polis with
IDP_ENABLED=true.
IDP_ENABLED is the deployment-wide switch. A connection follows it unless it
sets idpInitiatedLoginEnabled explicitly: true always allows IdP-initiated
login for that connection and false always blocks it. On Ory Network the
switch stays off and the Console toggle sets the per-connection flag, so no
deployment-wide change is needed.
The code hint is single use, expires with the code store TTL, and is only valid for the exact connection it was issued for. SP-initiated codes cannot be used as hints. If a hint is invalid or already consumed, the user is sent through the regular SP-initiated redirect instead — usually completing silently against the identity provider's existing session.
This is now available on Ory Network, for the Ory Enterprise License, and will be part of the next Ory Open Source release.
Ory Elements and Ory Terraform
No significant changes in this release.