A social knowledge tool for researchers built on ATProto
1import { Controller } from '../../../../../shared/infrastructure/http/Controller';
2import { Request, Response } from 'express';
3import { RefreshAccessTokenUseCase } from '../../../application/use-cases/RefreshAccessTokenUseCase';
4import { CookieService } from '../../../../../shared/infrastructure/http/services/CookieService';
5
6export class RefreshAccessTokenController extends Controller {
7 constructor(
8 private refreshAccessTokenUseCase: RefreshAccessTokenUseCase,
9 private cookieService: CookieService,
10 ) {
11 super();
12 }
13
14 async executeImpl(req: Request, res: Response): Promise<any> {
15 try {
16 // Try to get refresh token from cookie first, then fall back to request body
17 let refreshToken =
18 this.cookieService.getRefreshToken(req) || req.body?.refreshToken;
19
20 if (!refreshToken) {
21 return this.badRequest(res, 'Refresh token is required');
22 }
23
24 const result = await this.refreshAccessTokenUseCase.execute({
25 refreshToken,
26 });
27
28 if (result.isErr()) {
29 // Clear cookies when refresh fails
30 this.cookieService.clearTokens(res);
31 return this.fail(res, result.error);
32 }
33
34 // Set new tokens in cookies
35 this.cookieService.setTokens(res, {
36 accessToken: result.value.accessToken,
37 refreshToken: result.value.refreshToken,
38 });
39
40 // Also return tokens in response body for backward compatibility
41 return this.ok(res, result.value);
42 } catch (error: any) {
43 // Clear cookies on unexpected errors too
44 this.cookieService.clearTokens(res);
45 return this.fail(res, error);
46 }
47 }
48}