parseBody($request); try { $user = $authenticateUser->execute( new AuthenticateUserRequest( email: $data['email'] ?? null, password: $data['password'] ?? null, ) ); } catch (BadRequestException $exception) { return $this->errorResponse( $response, 400, $exception->getMessage() ); } catch (UnauthorizedException $exception) { return $this->errorResponse( $response, 401, $exception->getMessage() ); } $session = $createSession->execute($user); return $this->userResponse($response, $user) ->withHeader( 'Set-Cookie', $this->buildSetCookie($session->getToken()) ); } public function register( Request $request, Response $response, CreateUser $createUser, CreateSession $createSession, ): Response { $data = $this->parseBody($request); try { $user = $createUser->execute(new CreateUserRequest( email: $data['email'] ?? null, password: $data['password'] ?? null, isAdmin: false, )); } catch (BadRequestException $exception) { return $this->errorResponse( $response, 400, $exception->getMessage() ); } $session = $createSession->execute($user); return $this->userResponse($response, $user) ->withHeader( 'Set-Cookie', $this->buildSetCookie($session->getToken()) ); } public function logout( Request $request, Response $response, SessionRepository $sessionRepo, ): Response { $cookies = $request->getCookieParams(); $token = $cookies[AuthMiddleware::COOKIE_NAME] ?? null; if ($token !== null) { $sessionRepo->deleteByToken($token); } return $response->withStatus(204) ->withHeader('Set-Cookie', $this->buildClearCookie()); } public function me(Request $request, Response $response): Response { $user = $request->getAttribute('user'); if (!$user instanceof User) { return $this->errorResponse( $response, 401, 'unauthenticated' ); } return $this->userResponse($response, $user); } private function parseBody(Request $request): array { return json_decode((string) $request->getBody(), true) ?? []; } private function userResponse(Response $response, User $user): Response { $response->getBody()->write(json_encode([ 'user' => [ 'id' => $user->getId(), 'email' => (string) $user->getEmail(), 'isAdmin' => $user->isAdmin(), ], ])); return $response->withHeader( 'Content-Type', 'application/json' ); } private function errorResponse( Response $response, int $status, string $message, ): Response { $response->getBody()->write( json_encode(['error' => $message]) ); return $response->withStatus($status) ->withHeader('Content-Type', 'application/json'); } private function buildSetCookie(string $token): string { $maxAge = self::COOKIE_MAX_AGE; return AuthMiddleware::COOKIE_NAME . '=' . $token . '; Path=/; HttpOnly; SameSite=Lax; Max-Age=' . $maxAge; } private function buildClearCookie(): string { return AuthMiddleware::COOKIE_NAME . '=;' . ' Path=/; HttpOnly; SameSite=Lax; Max-Age=0'; } }