feat(auth): session/proxy auth for Wiki.js buttons; drop browser API key
The wikijs-integration.js embedded a full-privilege API key that was served to every wiki visitor — it unlocked all 66 authenticated endpoints, including page/vector deletes and index purges. That key has been rotated out of service. The two browser endpoints (/ingest/page, /entity-linking/link-page) now authenticate via the NPM /library-desk/ proxy location instead of a key: Authentik forward-auth for external users, LAN bypass for internal, verified by a trusted proxy marker header. This is safe because library-desk binds loopback-only, so NPM is the sole path that can set that header. The browser holds no secret; the script calls same-origin with credentials. Machine callers (the Scheduler) keep the Bearer key on the container-network endpoints. verify_api_key now compares in constant time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,21 +2,28 @@
|
||||
* Library Desk Integration for Wiki.js
|
||||
* Combined re-index and entity linking buttons
|
||||
*
|
||||
* Usage: Add to Wiki.js Code Injection:
|
||||
* <script src="http://192.168.86.149:8089/static/wikijs-integration.js"></script>
|
||||
* Usage: Add to Wiki.js Code Injection (served same-origin behind Authentik):
|
||||
* <script src="/library-desk/static/wikijs-integration.js"></script>
|
||||
*
|
||||
* Auth: none in the browser. Requests go same-origin through the NPM
|
||||
* /library-desk/ location, which is gated by Authentik forward-auth with the
|
||||
* LAN bypass — external users are authenticated, LAN users pass through, and
|
||||
* library-desk trusts the proxy marker header. No API key is embedded here.
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// Auto-detect Library Desk URL
|
||||
// Same-origin base: the script is served from <origin>/library-desk/static/...,
|
||||
// so strip '/static/...' to get the library-desk mount point on this origin.
|
||||
const scriptTag = document.currentScript;
|
||||
const scriptUrl = scriptTag ? scriptTag.src : '';
|
||||
const libraryDeskUrl = scriptUrl ? scriptUrl.split('/static/')[0] : 'http://192.168.86.149:8089';
|
||||
const libraryDeskUrl = scriptUrl
|
||||
? scriptUrl.replace(/^https?:\/\/[^/]+/, '').split('/static/')[0]
|
||||
: '/library-desk';
|
||||
|
||||
// Shared configuration
|
||||
const CONFIG = window.LIBRARY_DESK_CONFIG || {
|
||||
libraryDeskUrl: libraryDeskUrl,
|
||||
apiKey: 'af88ed8f44bed81bdb20d0534f1c4547340b29e2aba4963f61a71b993d7eb6e5',
|
||||
user: 'jpmschweitzer',
|
||||
buttonPosition: 'toolbar', // 'toolbar' or 'floating'
|
||||
debug: true
|
||||
@@ -229,8 +236,8 @@
|
||||
// Re-index directly
|
||||
const response = await fetch(CONFIG.libraryDeskUrl + '/ingest/page', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + CONFIG.apiKey,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
@@ -334,8 +341,8 @@
|
||||
// Call entity linking endpoint
|
||||
const response = await fetch(CONFIG.libraryDeskUrl + '/entity-linking/link-page', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + CONFIG.apiKey,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
|
||||
Reference in New Issue
Block a user