From b820e690f0d40d9f53de8cb8a230b96a67c9923b Mon Sep 17 00:00:00 2001 From: wizardchen Date: Fri, 5 Jun 2026 18:44:05 +0800 Subject: [PATCH] fix(auth): allow anonymous access to share-link endpoints (#1617) The global Auth middleware allowlist (noAuthAPI) was missing the share-link routes, so an unauthenticated invitee opening /register?token= hit a 401 on /auth/invitations/lookup and the frontend bounced them to /login instead of showing the register page. Add both share-link endpoints to the allowlist and stop the request interceptor from treating their 401s as a session-expiry redirect. Refs: https://github.com/Tencent/WeKnora/issues/1617 --- frontend/src/utils/request.ts | 7 ++++++- internal/middleware/auth.go | 26 +++++++++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/frontend/src/utils/request.ts b/frontend/src/utils/request.ts index bbdd146c..6be3c3a5 100644 --- a/frontend/src/utils/request.ts +++ b/frontend/src/utils/request.ts @@ -63,7 +63,12 @@ instance.interceptors.request.use( let isRefreshing = false; let failedQueue: Array<{ resolve: Function; reject: Function }> = []; -const PUBLIC_AUTH_PATHS = ['/auth/auto-setup', '/auth/login', '/auth/register', '/auth/oidc/']; +// Share-link endpoints (/auth/invitations/lookup, /auth/register-by-invite) +// are reachable by anonymous users opening an invite link. A 401 from these +// must surface to the page (e.g. expired token), not trigger the +// refresh-then-redirect-to-login flow (issue #1617). '/auth/register' already +// covers '/auth/register-by-invite' via substring match. +const PUBLIC_AUTH_PATHS = ['/auth/auto-setup', '/auth/login', '/auth/register', '/auth/oidc/', '/auth/invitations/lookup']; function isPublicAuthRequest(url?: string): boolean { if (!url) return false; diff --git a/internal/middleware/auth.go b/internal/middleware/auth.go index 490adf19..579246bb 100644 --- a/internal/middleware/auth.go +++ b/internal/middleware/auth.go @@ -20,15 +20,23 @@ import ( // 无需认证的API列表 var noAuthAPI = map[string][]string{ - "/health": {"GET"}, - "/api/v1/auth/register": {"POST"}, - "/api/v1/auth/login": {"POST"}, - "/api/v1/auth/auto-setup": {"POST"}, - "/api/v1/auth/config": {"GET"}, - "/api/v1/auth/oidc/config": {"GET"}, - "/api/v1/auth/oidc/url": {"GET"}, - "/api/v1/auth/oidc/callback": {"GET"}, - "/api/v1/auth/refresh": {"POST"}, + "/health": {"GET"}, + "/api/v1/auth/register": {"POST"}, + "/api/v1/auth/login": {"POST"}, + "/api/v1/auth/auto-setup": {"POST"}, + // Share-link surfaces accept a plaintext invite token from anonymous + // callers (an invitee who hasn't registered yet). They are registered + // as public routes in RegisterAuthRoutes and rate-limited by IP, so the + // global Auth middleware must let them through — otherwise opening a + // share link while logged out 401s and the frontend bounces the user to + // /login instead of the register page (issue #1617). + "/api/v1/auth/invitations/lookup": {"POST"}, + "/api/v1/auth/register-by-invite": {"POST"}, + "/api/v1/auth/config": {"GET"}, + "/api/v1/auth/oidc/config": {"GET"}, + "/api/v1/auth/oidc/url": {"GET"}, + "/api/v1/auth/oidc/callback": {"GET"}, + "/api/v1/auth/refresh": {"POST"}, // IM platforms (Feishu, Slack, etc.) commonly issue a HEAD request // before GET to validate Content-Type / Content-Length when rendering // image previews — both verbs must be allowed for image links to work.