- DATE:
- AUTHOR:
- Ory Team
Ory Hydra, Ory Kratos, Ory Polis v26.3.17 released
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.