From 30a4cda178759be4b9bfa52dcd1d9fb5b4b9bdd0 Mon Sep 17 00:00:00 2001 From: saridsa2 Date: Mon, 23 Mar 2026 11:53:02 +0530 Subject: [PATCH] feat: add token refresh endpoint for auto-renewal POST /auth/refresh exchanges refresh token for new access token via platform's renewToken mutation. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/auth/auth.controller.ts | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 09217ad..bce2340 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -146,4 +146,44 @@ export class AuthController { throw new HttpException('Authentication service unavailable', 503); } } + + @Post('refresh') + async refresh(@Body() body: { refreshToken: string }) { + if (!body.refreshToken) { + throw new HttpException('refreshToken required', 400); + } + + this.logger.log('Token refresh request'); + + try { + const res = await axios.post(this.graphqlUrl, { + query: `mutation RefreshToken($token: String!) { + renewToken(appToken: $token) { + tokens { + accessOrWorkspaceAgnosticToken { token expiresAt } + refreshToken { token } + } + } + }`, + variables: { token: body.refreshToken }, + }, { + headers: { 'Content-Type': 'application/json' }, + }); + + if (res.data.errors) { + this.logger.warn(`Token refresh failed: ${res.data.errors[0]?.message}`); + throw new HttpException('Token refresh failed', 401); + } + + const tokens = res.data.data.renewToken.tokens; + return { + accessToken: tokens.accessOrWorkspaceAgnosticToken.token, + refreshToken: tokens.refreshToken.token, + }; + } catch (error) { + if (error instanceof HttpException) throw error; + this.logger.error(`Token refresh failed: ${error}`); + throw new HttpException('Token refresh failed', 401); + } + } }