Skip to content

feat: Authenticate WebSocket provider connections to secured remote servers#2365

Open
dirkwa wants to merge 6 commits intoSignalK:masterfrom
dirkwa:fix-ws-provider-auth
Open

feat: Authenticate WebSocket provider connections to secured remote servers#2365
dirkwa wants to merge 6 commits intoSignalK:masterfrom
dirkwa:fix-ws-provider-auth

Conversation

@dirkwa
Copy link
Contributor

@dirkwa dirkwa commented Feb 25, 2026

Summary

  • Add token-based authentication for WebSocket provider (Data Connection) connections to remote Signal K servers
  • Token is sent on connect and verified via /signalk/v1/api/self on the remote server
  • Add proxy endpoints (testConnectionrequestAccesscheckAccessRequest) so the admin UI can interact with remote servers for token management
  • Add TokenInput UI component in R19 admin UI with manual token entry, "Request Access" and "Test Connection" buttons
  • Change default selfHandling from noSelf to useRemoteSelf
  • Add disconnect and error event handlers with status messages including auth hints
  • Include R19 admin UI corrections (Form.Select, expiration default, enabled on click, runDiscovery after delete)

Manual testing performed

  • Created device access request on secured remote server (192.168.0.147:3000) via API and approved it
  • Configured WS provider Data Connection on dev server (localhost:4000) with host, port, and device token
  • Verified authenticated WS connection established successfully — status shows "ws connection connected"
  • Verified deltas from remote server visible in Data Browser on local server
  • Fixed verifyRemoteToken — was using /skServer/loginStatus which returns notLoggedIn for valid device tokens; now uses /signalk/v1/api/self (200 = valid, 401 = invalid)
  • Verified R19 Access Requests UI renders correctly (Form.Select, NEVER expiration default)
  • Verified new Data Connection defaults to enabled
  • Verified runDiscovery triggers after provider delete

Fixes #2269
Fixes #875

@dirkwa dirkwa force-pushed the fix-ws-provider-auth branch from fba5ce5 to e9cbc5d Compare February 25, 2026 16:21
@dirkwa dirkwa force-pushed the fix-ws-provider-auth branch 2 times, most recently from 10b7ce7 to 6492af4 Compare February 26, 2026 19:12
Copy link
Member

@tkurki tkurki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Authenticate WebSocket provider connections to secured remote servers" is a nice addition, but per the project's PR guidelines:

One logical change per PR. Refactoring and behavior changes belong in separate PRs. If changes would result in multiple changelog entries, they should be separate PRs.

This PR bundles several independent changes that should be split. Each of the following would have its own changelog entry and can be reviewed/reverted/bisected independently:


1. fix: Reject revoked tokens instead of downgrading to anonymous read-only

Files: src/tokensecurity.ts, src/interfaces/ws.js

This is a security behavior change where invalid tokens now get a 401 instead of silently falling through to anonymous readonly. It's independently valuable and already exists as a standalone commit (b24f0c7). Should be its own PR.

2. feat: Authenticate WebSocket provider connections to secured remote servers

Files: packages/streams/mdns-ws.js, packages/server-admin-ui/src/views/ServerConfig/BasicProvider.js (selfHandling default)

The core feature: sending the token over the WS connection, verifying it against /loginStatus, disconnecting on failure, and the selfHandling conditional logic + default change. This is the main PR topic.

3. feat: Add token management UI and backend endpoints for WS provider connections

Files: packages/server-admin-ui-react19/src/views/ServerConfig/BasicProvider.tsx (+319/-26), src/interfaces/providers.js (+171 lines)

Large UI feature (TokenInput, Request Access flow, Test Connection) with three new backend API endpoints (/testConnection, /requestAccess, /checkAccessRequest). This depends on #2 but is a substantial, separately reviewable addition.

4. feat: Show resolved IP address per mDNS discovery entry

Files: src/discovery.js

Completely unrelated to authentication. Changes the discovery ID format and adds the address field. Independent enhancement.

5. fix: Reconnect admin WebSocket after login/logout

Files: packages/server-admin-ui-react19/src/actions.ts, packages/server-admin-ui-react19/src/services/WebSocketService.ts

Standalone bug fix so admin event subscriptions (ACCESS_REQUEST, etc.) work after auth state changes. Also adds the RECEIVE_LOGIN_STATUS handler.

6. fix: Miscellaneous R19 admin UI corrections

Files: AccessRequests.tsx, Devices.tsx, ProvidersConfiguration.tsx, AccessRequests.js

Groups several unrelated small fixes that could even be further split:

  • Form.Control type="select"Form.Select (React Bootstrap 5 migration)
  • Default expiration '1y''NEVER' on access request approval (behavior change)
  • Set discovered & configured providers to enabled: true
  • Re-run discovery after deleting a provider

Suggested dependency chain

#1 (reject revoked tokens)
└─► #2 (WS provider auth)
└─► #3 (token management UI + endpoints)

#4 (mDNS discovery IPs) — independent
#5 (reconnect admin WS) — independent
#6 (misc UI fixes) — independent

Recommendation

Split this into at minimum 4 PRs:

  1. #1 — security fix for revoked tokens
  2. #2 + #3 combined if you prefer, since the UI is tightly coupled to the feature (though separating them would make review easier given the +345 line diff in BasicProvider.tsx)
  3. #4 — mDNS discovery enhancement
  4. #5 + #6 — admin UI fixes (these are at least all UI-layer, though the expiration default change touches behavior)

This makes each PR easier to review, safer to revert if needed, and produces cleaner, more human friendly release notes.

@dirkwa dirkwa force-pushed the fix-ws-provider-auth branch from 6492af4 to e2a6d85 Compare March 3, 2026 23:11
@dirkwa dirkwa changed the title Authenticate WebSocket provider connections to secured remote servers feat: Authenticate WebSocket provider connections to secured remote servers Mar 4, 2026
@dirkwa dirkwa force-pushed the fix-ws-provider-auth branch from 40c6a6f to 3bca62d Compare March 5, 2026 18:23
@dirkwa dirkwa requested a review from tkurki March 11, 2026 23:23
@tkurki tkurki added the feature label Mar 12, 2026
Copy link
Member

@tkurki tkurki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me, just that is "Add proxy endpoints (testConnection, requestAccess, checkAccessRequest) so the admin UI can interact with remote servers for token management" in PR description leftover? Don't see it in the code, am I just blind?

@tkurki tkurki added this to the 2.24 milestone Mar 12, 2026
@dirkwa
Copy link
Contributor Author

dirkwa commented Mar 12, 2026

This looks good to me, just that is "Add proxy endpoints (testConnection, requestAccess, checkAccessRequest) so the admin UI can interact with remote servers for token management" in PR description leftover? Don't see it in the code, am I just blind?

It is in commit bbfabb23 which adds them to src/interfaces/providers.js (testConnection, requestAccess, checkAccessRequest).

@dirkwa dirkwa force-pushed the fix-ws-provider-auth branch 2 times, most recently from a6358a7 to ae74973 Compare March 15, 2026 23:11
@dirkwa dirkwa requested a review from tkurki March 16, 2026 02:01
dirkwa added 6 commits March 24, 2026 06:40
…ervers

Add token-based authentication for outgoing WebSocket provider
connections. When a token is configured, the provider sends it upon
connecting and verifies it against the remote server's login status
endpoint. Invalid tokens trigger a disconnect with a clear error.

Add server-side proxy endpoints (testConnection, requestAccess,
checkAccessRequest) that let the admin UI interact with remote Signal K
servers for token management. Deduplicate mDNS discovery results and
change the default self-handling to useRemoteSelf for both admin UIs.
Add TokenInput component to the SignalK provider configuration form
with Request Access and Test Connection buttons. Request Access sends
an access request to the remote server and polls for approval, filling
in the token automatically when granted. Test Connection verifies
connectivity and authentication status.
The /skServer/loginStatus endpoint returns notLoggedIn for device
tokens even when they are valid. Use /signalk/v1/api/self instead
which returns 200 for any authenticated request.
Move testConnection (renamed to testSignalKConnection), requestAccess,
and checkAccessRequest routes from providers.js to serverroutes.ts as
they are not provider-specific. Convert to TypeScript.
Add addAdminMiddleware to testSignalKConnection, requestAccess, and
checkAccessRequest endpoints. These accept user-supplied host/port and
make outbound HTTP requests from the server, which is an SSRF vector
without authentication.
@dirkwa dirkwa force-pushed the fix-ws-provider-auth branch from 085c105 to 857e839 Compare March 23, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error: Missing access token at strategy.authorizeWS Authentication for server to server connections

2 participants