From 1ea5f66ea3f436a1a813d3dd891acddb61088899 Mon Sep 17 00:00:00 2001 From: Ultradesu Date: Wed, 8 Apr 2026 16:01:16 +0100 Subject: [PATCH] fix(node-player): add offline_access scope and server-side token refresh - Add offline_access to OIDC scope so Authentik issues a refresh token - /auth/token now checks if access token is expired and refreshes it server-side before returning to the client Co-Authored-By: Claude Opus 4.6 (1M context) --- furumi-node-player/server/src/index.ts | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/furumi-node-player/server/src/index.ts b/furumi-node-player/server/src/index.ts index b72a382..dabe8b2 100644 --- a/furumi-node-player/server/src/index.ts +++ b/furumi-node-player/server/src/index.ts @@ -24,7 +24,7 @@ const oidcConfig = { clientSecret: process.env.OIDC_CLIENT_SECRET ?? '', authorizationParams: { response_type: 'code', - scope: process.env.OIDC_SCOPE ?? 'openid profile email', + scope: process.env.OIDC_SCOPE ?? 'openid profile email offline_access', }, }; @@ -74,7 +74,7 @@ app.get('/auth/me', (req, res) => { }); }); -app.get('/auth/token', (req, res) => { +app.get('/auth/token', async (req, res) => { if (disableAuth) { res.status(204).end(); return; @@ -85,17 +85,27 @@ app.get('/auth/token', (req, res) => { return; } - const accessToken = req.oidc.accessToken?.access_token; - const expiresAt = req.oidc.accessToken?.expires_in; - if (!accessToken) { + let accessToken = req.oidc.accessToken; + if (!accessToken?.access_token) { res.status(500).json({ error: 'no access token in session' }); return; } + // Refresh if expired + if (accessToken.isExpired()) { + try { + accessToken = await accessToken.refresh(); + } catch (e) { + console.error('Token refresh failed:', e); + res.status(401).json({ error: 'token refresh failed' }); + return; + } + } + res.json({ - access_token: accessToken, + access_token: accessToken.access_token, token_type: 'Bearer', - expires_in: expiresAt, + expires_in: accessToken.expires_in, }); });