DATE:
AUTHOR:
Ory Team
Ory Hydra Ory Kratos Ory Polis Ory Enterprise License

Ory Hydra, Ory Kratos, Ory Polis v26.3.17 released

DATE:
AUTHOR: Ory Team

Ory Hydra

Loopback redirect URIs now require a matching scheme

OAuth 2.0 loopback redirects (RFC 8252 section 7.3) with a dynamic port are now accepted only when the registered redirect URI also uses the http scheme. Previously, a client registered with an https loopback redirect URI, such as https://127.0.0.1/callback, also accepted plain http redirects to any port on that host.

Breaking changes

After upgrading, OAuth2 authorization requests fail redirect URI validation if the client registers only an https loopback URI but the native app requests an http loopback URI with a dynamic port.

To restore the flow, update the OAuth2 client's redirect_uris so the registered URI uses the same scheme, loopback address, path, and query as the URI requested by the app. The port may remain dynamic. For example, if the app requests http://127.0.0.1:<port>/callback, register http://127.0.0.1/callback. For IPv6, register http://[::1]/callback.


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

End Ory sessions when the upstream OpenID Connect provider signs the user out

Social sign-in providers can now end the Ory session they created, using OpenID Connect Front-Channel Logout 1.0. Set front_channel_logout: true on the provider, and register https://<your-ory-domain>/self-service/methods/oidc/frontchannel-logout/<provider-id> as that provider's front-channel logout URL with frontchannel_logout_session_required enabled. Each provider has its own logout URL, and can only end sessions created through itself. When the user signs out at the provider, Ory revokes the session that sign-in created.

The provider must return the sid claim in the ID token, and the provider's claims_source must be id_token (the default). The mechanism relies on third-party cookies and therefore only works in browsers that still allow them. Nothing changes for providers that leave front_channel_logout unset, and the Ory session cookie's own SameSite behavior is unchanged.


This is now available on Ory Network and for the Ory Enterprise License.


Ory Polis

DSYNC_WEBHOOK_LOGS_TTL rejects a value that is not a duration

DSYNC_WEBHOOK_LOGS_TTL summed whichever <number><unit> tokens appeared anywhere in its value, so a typo carrying one was accepted as a retention rather than reported: 1d garbage kept logs for a day, and typo1h for an hour. The release that added the setting described this leniency, but it means a mistyped value changes how long logs are kept and says nothing about it.

A value must now be a duration end to end, such as 720h, 30d or 1d 12h. Anything else falls back to the seven-day default and logs a warning, which is what an unrecognized value has always done. Unset still means seven days and an empty value still keeps logs indefinitely, and now says so in a warning of its own, because a store with no expiry grows for as long as the deployment runs.

Breaking: a value that carries a duration inside something else kept logs for that duration and now keeps them for seven days. 1d garbage and typo1h are the shapes this catches. Check the value before upgrading if you set this; spaced durations such as 1d 12h are unaffected and still mean what they say.

SSO_TRACES_TTL and DSYNC_WEBHOOK_LOGS_TTL now resolve their retention through one shared function, so a duration, an empty value and a typo mean the same thing in both.

SSO_TRACES_TTL now applies in both directions

SSO_TRACES_TTL reached the trace store, which expires the records, but a second cleanup inside Polis deleted anything older than a hardcoded week and never read the setting. Whichever of the two was shorter won, so a value below seven days took effect and a value above it was silently capped at seven. The direction people set this for -- keeping traces long enough to investigate a failure reported weeks later -- was the one that did nothing.

That cleanup is gone and retention is the store's own expiry, so the setting now means what it says. Leaving it unset still keeps traces for seven days.

SSO_TRACES_TTL still takes a number of hours, and now also takes a duration such as 720h or 30d, matching DSYNC_WEBHOOK_LOGS_TTL. Set it to an empty value to keep traces indefinitely. A value that is not a duration end to end falls back to the seven-day default and logs a warning, so a typo never silently changes retention.

Setting it to an empty value now survives option normalization as well. The package filled an unset trace TTL with its seven-day default using a falsy check, which turned the zero that means indefinite back into seven days, so there was no way to ask for it at all.

Breaking: a deployment that declares SSO_TRACES_TTL with an empty value kept traces for seven days and now keeps them indefinitely. If you set the variable but leave it blank, either remove it or give it a retention such as 168h, otherwise the trace table grows for as long as the deployment runs. Polis logs a warning at startup whenever traces are kept indefinitely.

Bulk deletes now remove every record, not just the first page

Deleting all SSO connections for a tenant and product removed only as many connections as a single database read returns, which is capped by DB_PAGE_LIMIT and defaults to 50. The call still reported success, so a tenant with more connections than that was left with working SSO connections after what looked like a complete deprovision. Deleting traces for a product had the same problem and stopped after 50 traces.

Both now page through every matching record. If you have deprovisioned a tenant with more than DB_PAGE_LIMIT SSO connections, run the delete again to clear whatever was left behind, or list the connections for that tenant and product to check.

On MongoDB, paged reads could also repeat some records and skip others when they shared a creation time, which bulk imports make common. Each record now appears exactly once.

Find a customer's SSO connections and directories by tenant

The Admin Portal listed every SSO connection and every directory a page at a time with no way to ask for one customer's, so finding them meant paging until they appeared, and finding both meant doing it twice.

Both lists now take a tenant and a product and answer with that customer's records. A tenant in either list is also a link to the same tenant on the other, so a connection leads to the directories beside it and back.

Both terms are needed and each has to match what was stored: records are indexed by tenant and product together, so this is a lookup rather than a search. The same two parameters work on GET /api/admin/connections and GET /api/admin/directory-sync, which answer with the customer's records in full and no pagination.

Reading a customer's directories by tenant and product returned only as many as a single database read yields, which DB_PAGE_LIMIT caps and defaults to 50, so a customer with more directories than that saw a short list with nothing to indicate records were missing. It now reads through to the end, which also affects GET /api/v1/dsync and the setup link that lists a customer's directories.

Find a directory's users and groups by email or name

The Admin Portal listed a directory's users and groups a page at a time with no way to ask for one of them, so answering whether a person had been provisioned meant paging through the directory until their row appeared.

Both lists now take a term and answer with the matching record. The same parameters work on GET /api/admin/directory-sync/{directoryId}/users, which takes email, and GET /api/admin/directory-sync/{directoryId}/groups, which takes name. Either answers with the record itself and without pagination, since a directory holds one user per address and one group per name.

The term has to match what the identity provider sent, in full: users are indexed by directory and email together and groups by directory and name, so this is a lookup rather than a search. A partial address or name is a different key and finds nothing, which the field says above the list.

A user whose email address changed after they were provisioned, or a group that was renamed, is still indexed under the value it was created with, so the lookup answers to that value and not to the current one. Those records remain in the unfiltered list.

SCIM user and group listings now page past the first set of records

Listing directory users or groups over SCIM reported the first page as the whole directory, so an identity provider reading the list stopped after DB_PAGE_LIMIT records and never saw the rest. Group listings ignored startIndex and count altogether and answered every request with the same records.

Both endpoints now honour startIndex and count and report a totalResults that keeps the caller paging until the directory is exhausted. totalResults is a lower bound while more records remain and becomes exact on the final page, so a client that pages until it has seen totalResults records now reads the whole directory. If a directory looked short in your identity provider, run a synchronisation again to pick up the records that were never returned.


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


Ory Network, Ory Keto, Ory Oathkeeper, Ory Elements, and Ory Terraform

No significant changes in this release.

Powered by LaunchNotes