Security
There was a security issue with Moderate severity during token refresh under some circumstances that allows cross-client token minting and identity/scope confusion during token refresh. You should do a timely update or at least make sure you are not vulnerable. If you run the default config, you should be good.
If you have public clients with the refresh_token flow enabled and either you have configured dynamic_clients.enable = true + dynamic_clients.reg_token not set or ephemeral_clients.enabled = true + ephemeral_clients.allowed_flows contains refresh_token, it
might be possible to abuse an issue. There is a slight chance to make it work without ephemeral or dynamic clients, but that is out of Rauthys control. The main thread comes from the combination of a public client with allowed token refresh, and a stolen or leaked refresh token.
An advisory and CVE / PoC will be made public at a later point.
Changes
Per-Client Favicons
Client branding now supports a dedicated browser favicon for each client, independently of the login logo. Favicons can be uploaded, previewed, and removed from the Admin UI.
Session MFA Upgrade after Passkey Registration
Registering a Passkey from the Account dashboard upgrades the current session to MFA now. Before, is_mfa stayed false until the next login, which meant a fresh admin account that just enrolled its first Passkey was still rejected by admin_force_mfa and had to log out and back in. The Account dashboard also updates the MFA indicator directly after registering or deleting a Passkey instead of only after a manual page reload.
Token Exchange (RFC 8693)
Rauthy supports the RFC 8693 token exchange now, via the urn:ietf:params:oauth:grant-type:token-exchange grant on the existing token endpoint. It lets a service trade an access token it received for one that is scoped to a downstream service, instead of forwarding a token that was never minted for that target.
Both impersonation and delegation are supported. With an actor_token, the exchanged token carries an act claim naming the acting party, so a resource server can tell "A acting for B" apart from "B"; a delegation chain stays nested inside it.
The exchange is deny-by-default and needs two things on the exchanging client: token_exchange in its flows_enabled, and the requested target in its allowed_resources, which is the same allow-list the RFC 8707 resource indicators use. Only confidential clients may exchange.
Rauthy only accepts access tokens as subject_token / actor_token, and only ever issues an access token in return. An exchanged token deliberately never comes with a refresh token. may_act is not supported yet.
RFC 8414 Metadata Endpoints
Rauthy now correctly serves the .well-known metadata documents under additional endpoints matching the RRFC 8414. This was necessary for CIMD discovery that's used by e.g. Claude.ai.
Opt-in to ignore unknown grant-types from ephemeral clients
This is a fix for clients relying on CIMD (like AI agents) when you don't have control over the client documents, and they include unknown / invalid grant types, even when they are unused.
[ephemeral_clients]
# A dynamic client registration is always rejected when it advertises a grant
# type Rauthy does not support. Some spec-valid CIMD clients (e.g. claude.ai)
# advertise an unsupported grant (`urn:ietf:params:oauth:grant-type:jwt-bearer`)
# in their metadata document without ever using it, which would otherwise cause
# the whole document to be rejected. Setting this to `true` lets an ephemeral
# (CIMD) client document through by sanitizing - stripping - the unsupported
# grant types instead of rejecting it.
#
# This applies ONLY to ephemeral clients. Dynamic client registration (DCR) and
# admin-managed clients always keep rejecting unknown grant types.
#
# default: false
# overwritten by: EPHEMERAL_CLIENTS_IGNORE_UNKNOWN_AUTH_FLOWS
ignore_unknown_auth_flows = falseRFC 8252 for localhost callbacks
Rauthy uses a more-strict requirement for redirect_uris back to localhost. If you want to match any port, you need to specifically allow it using the glob pattern with e.g. http://localhost:*. However, CIMD clients do not know this and rely on RFC 8252 which allows any port for localhost. This is the standard, but less secure. You can now opt-in to it:
[access]
# If set to `true`, loopback redirect URIs (to `localhost`, `127.0.0.1`
# or `[::1]`) will match on any port, as required by RFC 8252 section 7.3
# for native / CLI apps that bind an ephemeral loopback port at runtime.
# Both the port-less form and an explicit `*` wildcard are accepted for
# `localhost` when this is enabled.
#
# This only applies to dynamic and ephemeral clients. Static clients
# always require an exact match or an explicit `*` wildcard, even with
# this option set, because an admin has full control over their config.
#
# Only enable this if you need it, e.g. an MCP client whose loopback
# redirect port is not known in advance and cannot be pre-registered.
# It is `false` by default to keep redirect matching as strict as
# possible out of the box.
#
# default: false
# overwritten by: RFC_8252_ENABLE
rfc_8252_enable = falsepreferred_username during User Registration
It is now possible to provide a preferred_username during the user registration when using API Keys. This gets rid of an additional round-trip that was necessary when working with the API instead of the UI.
Relaxed regex for Client Names
Client names are now allowed to also contain ( and ).
Bugfix
- The
subclaim is now omitted from tokens if it isnullanyway.
#1655 - The
resourceclaim was dropped during UI-initiated, immediate session / login refreshes.
#1657 - A callback for an upstream auth provider login is deleted as soon as it has been validated now. Before, only a failed
state, XSRF token or PKCE verifier check deleted it. A callback that passed all three stayed in the cache until its 300 second TTL ran out, whether the login then succeeded or failed. This also makes the behaviour match what the function documented all along.
#1664 user.last_loginwas wrongly updated on token refreshes.
#1659