Summary
When CLN Application and Ride The Lightning (RTL) are served from the same hostname on different ports, opening RTL can cause CLN Application to fail its next authentication-status request with 403 Invalid CSRF token. Form tempered. CLN Application then displays its password dialog even when APP_SINGLE_SIGN_ON=true and the Umbrel session remains valid.
Browser cookies are scoped by hostname and path, not port. RTL writes a generic XSRF-TOKEN cookie at Path=/ on the shared hostname. Axios in CLN Application can consume that cookie for its XSRF header instead of the token CLN Application fetched from /v1/shared/csrf/.
Environment
- Umbrel / umbrelOS
- CLN Application image:
ghcr.io/elementsproject/cln-application:26.04
- CLN Application URL:
http://<host>:2103/cln
APP_SINGLE_SIGN_ON=true
- RTL URL:
http://<host>:3100/rtl
- Reproduced with RTL v0.15.8
- Reviewed RTL v0.15.12 source: it still uses the generic
XSRF-TOKEN cookie at Path=/
- Both apps use the same hostname and different ports
Steps to reproduce
- Log in to Umbrel normally.
- Open CLN Application and confirm it authenticates through SSO and displays node data without a password prompt.
- Open RTL on the same hostname in the same browser profile.
- Return to or reload CLN Application.
Actual behavior
CLN Application sends POST /v1/auth/isauthenticated/, receives HTTP 403, zeroes the displayed node data, and opens the password dialog.
Browser console:
Failed to load resource: the server responded with a status of 403 (Forbidden)
HTTP Request failed for post /auth/isauthenticated ... Invalid CSRF token. Form tempered.
Auth Status failed: Invalid CSRF token. Form tempered.
CLN Application server log at the same timestamps:
Invalid CSRF token. Form tempered.
This is misleading because the password is not wrong and SSO is still valid. lightningd remains healthy.
Confirmed recovery
Expiring only the XSRF-TOKEN cookie for the shared hostname at Path=/, then reloading CLN Application, immediately removes the password dialog and restores authenticated node data. Neither CLN Application nor lightningd needs to be restarted.
A direct HTTP test that shared only the _csrf cookie did not reproduce the failure. The real browser flow did reproduce it, which points specifically to Axios automatically reading RTL's visible XSRF-TOKEN cookie.
Relevant CLN Application behavior
CLN Application explicitly fetches a CSRF token from /v1/shared/csrf/ and assigns it to Axios's X-XSRF-TOKEN default header. However, Axios also has conventional XSRF-TOKEN cookie handling.
Separately, RootService.getAuthStatus() catches any request error and returns a state equivalent to unauthenticated with a valid password. Startup then opens the password modal, masking the underlying CSRF error.
Expected behavior
- Cookies created by another same-host application must not invalidate CLN Application requests.
- A CSRF/network error from
/auth/isauthenticated must not be presented as a password failure.
- With
APP_SINGLE_SIGN_ON=true, this failure should provide a recoverable error state rather than a password prompt.
Suggested fixes
- Give CLN Application unique XSRF cookie/header names, or disable Axios automatic
XSRF-TOKEN cookie consumption because CLN Application already fetches and sets its CSRF token explicitly.
- Consider scoping the CLN CSRF cookie to an application-specific path where deployment routing permits it.
- Preserve the actual authentication-status error in
getAuthStatus() and do not convert every exception into the password-login state.
I can provide additional sanitized network traces if needed.
Summary
When CLN Application and Ride The Lightning (RTL) are served from the same hostname on different ports, opening RTL can cause CLN Application to fail its next authentication-status request with
403 Invalid CSRF token. Form tempered.CLN Application then displays its password dialog even whenAPP_SINGLE_SIGN_ON=trueand the Umbrel session remains valid.Browser cookies are scoped by hostname and path, not port. RTL writes a generic
XSRF-TOKENcookie atPath=/on the shared hostname. Axios in CLN Application can consume that cookie for its XSRF header instead of the token CLN Application fetched from/v1/shared/csrf/.Environment
ghcr.io/elementsproject/cln-application:26.04http://<host>:2103/clnAPP_SINGLE_SIGN_ON=truehttp://<host>:3100/rtlXSRF-TOKENcookie atPath=/Steps to reproduce
Actual behavior
CLN Application sends
POST /v1/auth/isauthenticated/, receives HTTP 403, zeroes the displayed node data, and opens the password dialog.Browser console:
CLN Application server log at the same timestamps:
This is misleading because the password is not wrong and SSO is still valid.
lightningdremains healthy.Confirmed recovery
Expiring only the
XSRF-TOKENcookie for the shared hostname atPath=/, then reloading CLN Application, immediately removes the password dialog and restores authenticated node data. Neither CLN Application norlightningdneeds to be restarted.A direct HTTP test that shared only the
_csrfcookie did not reproduce the failure. The real browser flow did reproduce it, which points specifically to Axios automatically reading RTL's visibleXSRF-TOKENcookie.Relevant CLN Application behavior
CLN Application explicitly fetches a CSRF token from
/v1/shared/csrf/and assigns it to Axios'sX-XSRF-TOKENdefault header. However, Axios also has conventionalXSRF-TOKENcookie handling.Separately,
RootService.getAuthStatus()catches any request error and returns a state equivalent to unauthenticated with a valid password. Startup then opens the password modal, masking the underlying CSRF error.Expected behavior
/auth/isauthenticatedmust not be presented as a password failure.APP_SINGLE_SIGN_ON=true, this failure should provide a recoverable error state rather than a password prompt.Suggested fixes
XSRF-TOKENcookie consumption because CLN Application already fetches and sets its CSRF token explicitly.getAuthStatus()and do not convert every exception into the password-login state.I can provide additional sanitized network traces if needed.