getAuthRequestFromSession($request); $authRequest->setAuthorizationApproved(true); return $this->withErrorHandling(function () use ($authRequest, $psrResponse) { $response = $this->server->completeAuthorizationRequest($authRequest, $psrResponse); if ($this->isOutOfBandRequest($authRequest)) { $code = $this->extractAuthorizationCode($response); return response()->json([ 'code' => $code, 'state' => $authRequest->getState(), ]); } return $this->convertResponse($response); }, $authRequest->getGrantTypeId() === 'implicit'); } /** * Check if the request is an out-of-band OAuth request. * * @param AuthorizationRequest $authRequest * @return bool */ protected function isOutOfBandRequest($authRequest) { $redirectUri = $authRequest->getRedirectUri(); if ($redirectUri === 'urn:ietf:wg:oauth:2.0:oob') { return true; } // RFC 6749 ยง3.1.2.3 permits a client with a single registered redirect // URI to omit redirect_uri on the authorize request, in which case the // league server leaves the auth request's redirect URI null. Fall back // to the client's registered redirect URIs to still detect an OOB-only // client. Passport's client entity types getRedirectUri() as string|array. if ($redirectUri === null) { $registered = $authRequest->getClient()->getRedirectUri(); $registered = is_array($registered) ? $registered : [$registered]; return count($registered) === 1 && $registered[0] === 'urn:ietf:wg:oauth:2.0:oob'; } return false; } /** * Extract the authorization code from the PSR-7 response. * * @param ResponseInterface $response * @return string * * @throws OAuthServerException */ protected function extractAuthorizationCode($response) { $location = $response->getHeader('Location')[0] ?? ''; if (empty($location)) { throw OAuthServerException::serverError('Missing authorization code in response'); } parse_str(parse_url($location, PHP_URL_QUERY), $params); if (! isset($params['code'])) { throw OAuthServerException::serverError('Invalid authorization code format'); } return $params['code']; } }