Add token auth for live-server endpoints#23
Merged
Conversation
Generates a random 128-bit token at server start and threads it through:
* assets/index.html data-live-token attribute, withToken() helper
wrapping the content.md fetch and the SSE
EventSource URL. Token also read from URL
query and stashed in sessionStorage so
refreshes work without it on the URL.
* lua/.../init.lua ls_util.random_token() at server start,
substituted into index.html via __LIVE_TOKEN__,
passed to ls_server.start as cfg.token and
cfg.protected_paths = { "^/content%.md$" },
embedded in the auto-opened browser URL.
* lua/.../lock.lua token field in the lock JSON, mode 0600 so
the secret isn't world-readable on multi-user
systems. Secondary instances read it back.
* lua/.../remote.lua send_event(port, type, json, token); the
secondary scroll-sync RPC now includes the
token it read from the lockfile.
Static assets (index.html itself) remain reachable without a token so the
browser can bootstrap. content.md and both live-control endpoints are gated.
Depends on live-server.nvim cfg.token / cfg.protected_paths support.
Tests: 12/12 in tests/token_auth_test.lua covering token generation,
HTML substitution, content.md gating, and stop() cleanup.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Plumbs token-based authentication through the live-server endpoints so that with PR #13 (host binding to
0.0.0.0) about to land, LAN-exposed previews are actually safe to recommend instead of just warned about. Caller experience does not change: token is auto-generated, embedded in the auto-opened browser URL, and stashed insessionStorage. No new user config to set.Depends on
selimacerbas/live-server.nvim#4 (adds
cfg.tokenandcfg.protected_paths). Merge that one first.What changes
assets/index.htmldata-live-token="__LIVE_TOKEN__"attribute on<html>.LIVE_TOKENis read from the data attribute, then the URL?t=param, thensessionStorage, in that order, and stashed insessionStoragefor future loads.withToken(url)helper appends?t=<token>to URLs.fetch('content.md')andnew EventSource('/__live/events')calls.lua/markdown_preview/init.lualive_server.util.random_token(16).__LIVE_TOKEN__inindex.html(using function-formgsubto dodge the%-in-replacement-string Lua gotcha).token = M._tokenandprotected_paths = { "^/content%.md$" }tols_server.start.browser_url(port)helper.M.start()so the role decision (primary vs secondary) and token resolution happen beforewrite_index. Secondary instances read the token from the lockfile and adopt it.M.stop()clears_token.lua/markdown_preview/lock.luatokenfield to the lock JSON.0600so the secret isn't world-readable on multi-user systems.lua/markdown_preview/remote.luasend_event(port, type, json, token)now appends&t=<token>to the URL it builds, so the secondary scroll-sync RPC works against an auth-enabled primary.What does not change
127.0.0.1(changed by PR Add configurable host binding for external access #13, not here).index.html) remain reachable without a token; onlycontent.mdand the two live-control endpoints are gated. This matters because the browser bootstraps fromindex.htmlbefore any JS runs.Tests
tests/token_auth_test.lua, 12 cases:data-live-token="<current token>"./reachable without token (200)./content.mdreturns 401 without token, 200 with correct token; body contains the buffer text.M.stop()clears_tokenand_server_instance; port no longer responds.Run:
nvim --headless --clean -c "set rtp+=/path/to/live-server.nvim" -c "set rtp+=." -c "luafile tests/token_auth_test.lua" -c "qa!"Relation to PR #13
PR #13 adds the
hostbinding option with a README warning that the LAN exposure has no auth. This PR makes that warning soften-able: once both are merged,host = "0.0.0.0"is genuinely safe because anyone trying to readcontent.mdor hit/__live/injectfrom another machine needs the 128-bit token from the browser URL.🤖 Generated with Claude Code