feat(auth): allowlist private для LAN return_to
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+1
-1
@@ -13,7 +13,7 @@ ADMIN_PASSWORD=admin
|
||||
ADMIN_NAME=Admin
|
||||
|
||||
# Allowed return_to hosts (comma-separated), e.g. .shnt.top or full origins
|
||||
RETURN_TO_ALLOWLIST=.shnt.top,localhost,http://localhost:5173,http://localhost:5174
|
||||
RETURN_TO_ALLOWLIST=.shnt.top,localhost,private,http://localhost:5173,http://localhost:5174
|
||||
|
||||
# ReUI PRO (apps/web/components.json → @reui Authorization)
|
||||
# Ключ: https://reui.io/docs/license-setup — класть в apps/web/.env.local (gitignored)
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ services:
|
||||
ADMIN_EMAIL: ${ADMIN_EMAIL:[email protected]}
|
||||
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-}
|
||||
ADMIN_NAME: ${ADMIN_NAME:-Admin}
|
||||
RETURN_TO_ALLOWLIST: ${RETURN_TO_ALLOWLIST:-.shnt.top,localhost}
|
||||
RETURN_TO_ALLOWLIST: ${RETURN_TO_ALLOWLIST:-.shnt.top,localhost,private}
|
||||
LOG_LEVEL: info
|
||||
STATIC_DIR: /app/static
|
||||
volumes:
|
||||
|
||||
@@ -127,7 +127,8 @@ export function hasPermission(
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowlist entries: `.shnt.top`, `localhost`, or full origins `http://localhost:5173`.
|
||||
* Allowlist entries: `.shnt.top`, `localhost`, full origins `http://localhost:5173`,
|
||||
* or token `private` for RFC1918 LAN hosts (192.168/10/172.16-31).
|
||||
*/
|
||||
export function isReturnToAllowed(
|
||||
returnTo: string,
|
||||
@@ -146,7 +147,11 @@ export function isReturnToAllowed(
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean)
|
||||
|
||||
const allowPrivate = entries.some((e) => e.toLowerCase() === 'private')
|
||||
if (allowPrivate && isPrivateHostname(url.hostname)) return true
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.toLowerCase() === 'private') continue
|
||||
if (entry.startsWith('.')) {
|
||||
const suffix = entry.slice(1)
|
||||
if (url.hostname === suffix || url.hostname.endsWith(entry)) return true
|
||||
@@ -167,6 +172,18 @@ export function isReturnToAllowed(
|
||||
return false
|
||||
}
|
||||
|
||||
function isPrivateHostname(hostname: string): boolean {
|
||||
if (hostname === 'localhost' || hostname.endsWith('.local')) return true
|
||||
const m = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(hostname)
|
||||
if (!m) return false
|
||||
const a = Number(m[1])
|
||||
const b = Number(m[2])
|
||||
if (a === 10) return true
|
||||
if (a === 192 && b === 168) return true
|
||||
if (a === 172 && b >= 16 && b <= 31) return true
|
||||
return false
|
||||
}
|
||||
|
||||
export function buildSsoRedirectUrl(
|
||||
returnTo: string,
|
||||
accessToken: string,
|
||||
|
||||
Reference in New Issue
Block a user