Proxy requireAuth to auth service /verify for live permission checks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
24747919cd
commit
71f7cf560e
2 changed files with 14 additions and 25 deletions
|
|
@ -1,36 +1,24 @@
|
||||||
import { jwtVerify } from 'jose'
|
|
||||||
import { isOnsite } from './ip-check.js'
|
|
||||||
|
|
||||||
const APP_SLUG = process.env.APP_SLUG || 'noticeboard'
|
const APP_SLUG = process.env.APP_SLUG || 'noticeboard'
|
||||||
const secret = new TextEncoder().encode(process.env.CENTRAL_AUTH_SECRET || '')
|
const AUTH_URL = process.env.AUTH_URL || 'http://10.10.10.101:3001'
|
||||||
|
|
||||||
export async function requireAuth(request, reply) {
|
export async function requireAuth(request, reply) {
|
||||||
const token = request.cookies?.hnf_session
|
const cookie = request.headers.cookie || ''
|
||||||
if (!token) return reply.status(401).send({ error: 'Not authenticated' })
|
if (!cookie) return reply.status(401).send({ error: 'Not authenticated' })
|
||||||
|
|
||||||
let payload
|
let res
|
||||||
try {
|
try {
|
||||||
const { payload: p } = await jwtVerify(token, secret)
|
res = await fetch(`${AUTH_URL}/api/auth/verify?app=${APP_SLUG}`, {
|
||||||
payload = p
|
headers: { cookie },
|
||||||
|
signal: AbortSignal.timeout(3000),
|
||||||
|
})
|
||||||
} catch {
|
} catch {
|
||||||
return reply.status(401).send({ error: 'Invalid session' })
|
return reply.status(503).send({ error: 'Auth service unavailable' })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!payload.apps?.includes(APP_SLUG)) {
|
if (!res.ok) {
|
||||||
return reply.status(403).send({ error: 'No permission for this app' })
|
const body = await res.json().catch(() => ({}))
|
||||||
|
return reply.status(res.status).send(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offsite check — only for users without offsite_allowed flag
|
request.user = await res.json()
|
||||||
if (!payload.offsite_allowed) {
|
|
||||||
const clientIP = request.headers['x-real-ip'] || request.ip
|
|
||||||
if (!(await isOnsite(clientIP))) {
|
|
||||||
return reply.status(403).send({ error: 'Access restricted to site network' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
request.user = {
|
|
||||||
email: payload.sub,
|
|
||||||
name: payload.name,
|
|
||||||
is_admin: payload.is_admin ?? false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ services:
|
||||||
- CENTRAL_AUTH_SECRET=${CENTRAL_AUTH_SECRET}
|
- CENTRAL_AUTH_SECRET=${CENTRAL_AUTH_SECRET}
|
||||||
- APP_SLUG=noticeboard
|
- APP_SLUG=noticeboard
|
||||||
- OFFICE_IP_CHECK=${OFFICE_IP_CHECK:-disabled}
|
- OFFICE_IP_CHECK=${OFFICE_IP_CHECK:-disabled}
|
||||||
|
- AUTH_URL=${AUTH_URL:-http://10.10.10.101:3001}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3001/health || exit 1"]
|
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3001/health || exit 1"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue