sessionCache = new MonitorCacheKeys($sessionCache); } /** * @throws InvalidArgumentException */ #[Override] public function issue(string $identity, Scope $scope, Request $request, bool $json): Response { /* the same normalisation LoginManager has always applied, so cache keys * and Remote-User values stay identical between the two login paths */ $cleanId = $this->makeCacheKey($identity); $response = $this->authSuccessResponse($cleanId, $this->config); /* when the caller only wanted this one page, there is nothing to store */ if (Scope::None === $scope) { $this->logger->debug("successful login for: $cleanId"); return $response; } if (Scope::Cookie === $scope) { $response->headers->setCookie($this->setCookie($cleanId, $request->getHost())); } elseif (Scope::Ip === $scope) { $this->setIp($cleanId, (string) $request->getClientIp()); } if ($json) { $contentType = 'application/json'; $content = (string) json_encode([ 'message' => 'Login successful', 'nonce' => null, ]); } else { $contentType = 'text/html'; $content = "hi $cleanId, please reload"; } $location = $request->query->has('return') && $this->domainManager->validReturn((string) $request->query->get('return')) ? "{$request->query->get('return')}" : "{$request->getPathInfo()}{$request->getQueryString()}"; /* force redirect to use GET method (important when using central auth) */ $response->setContent($content) ->setStatusCode(Response::HTTP_SEE_OTHER) ->headers->set('Location', $location); $response->headers->set('Content-Type', $contentType); $this->logger->debug("successful login for: $cleanId"); return $response; } /** * @throws InvalidArgumentException */ private function setCookie(string $id, string $host): Cookie { /* successful auth with token, store session and set the cookie */ $ulid = new Ulid(); $sessionCookie = $this->sessionCache->getItem( $this->makeCacheKey("cookie_$ulid"), ); if ($sessionCookie->isHit()) { /* it is supposed to be impossible to have collisions */ $this->logger->error('aborting: ULID collision'); throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error'); } $sessionCookie->set($id); $sessionCookie->expiresAfter($this->config->cookieTtl()); $this->sessionCache->save($sessionCookie); return Cookie::create( name: $this->sessionCookieName($this->domainManager), value: $ulid->toString(), expire: time() + $this->config->cookieTtl(), path: '/', domain: $this->sessionCookieDomain($this->domainManager, $host), secure: true, httpOnly: true, sameSite: Cookie::SAMESITE_STRICT, ); } /** * @throws InvalidArgumentException */ private function setIp(string $id, string $ip): void { /* successful auth with token, requested scope of ip (and ip access enabled) */ $ipKey = $this->makeCacheKey("ip_$ip"); $sessionIp = $this->sessionCache->getItem($ipKey); $sessionIp->set($id); $sessionIp->expiresAfter($this->config->ipTtl()); $this->sessionCache->save($sessionIp); } }