validated(); $user = $userRepository->findByCredentials( new EmailAddress($credentials['email']), $credentials['password'], ); if ($user === null) { return new JsonResponse( ['error' => 'invalid_credentials'], 401, ); } $sessionLifetime = (int) config('session.lifetime', 120); $createdAt = $clock->now(); $expiresAt = $createdAt->add( new DateInterval("PT{$sessionLifetime}M"), ); $session = $sessionRepository->create(new CreateSessionDto( token: bin2hex(random_bytes(32)), user: $user, createdAt: $createdAt, expiresAt: $expiresAt, )); $response = new JsonResponse([ 'user' => $this->userPayload($user), ]); $response->headers->setCookie(new Cookie( name: AuthMiddleware::COOKIE_NAME, value: $session->getToken(), expire: $session->getExpiresAt(), path: $this->cookiePath(), domain: $this->cookieDomain(), secure: (bool) config('session.secure', false), httpOnly: true, sameSite: $this->cookieSameSite(), )); return $response; } public function me(Request $request): JsonResponse { /** @var User $user */ $user = $request->attributes->get('user'); return new JsonResponse([ 'user' => $this->userPayload($user), ]); } /** * @return array{id: int, email: string} */ private function userPayload(User $user): array { return [ 'id' => $user->getId(), 'email' => $user->getEmail()->value(), ]; } private function cookiePath(): string { $path = config('session.path', '/'); return is_string($path) ? $path : '/'; } private function cookieDomain(): ?string { $domain = config('session.domain'); return is_string($domain) ? $domain : null; } /** * @return ''|'lax'|'none'|'strict'|null */ private function cookieSameSite(): ?string { $sameSite = config('session.same_site', 'lax'); return match ($sameSite) { '' => '', Cookie::SAMESITE_LAX => Cookie::SAMESITE_LAX, Cookie::SAMESITE_NONE => Cookie::SAMESITE_NONE, Cookie::SAMESITE_STRICT => Cookie::SAMESITE_STRICT, default => null, }; } }