bearerToken() ?: $request->query('access_token', ''))); if ($rawToken === '') { return $this->invalidTokenResponse('Missing access token.'); } $accessToken = $this->tokenService->validateAccessToken($rawToken); if (! $accessToken || ! $accessToken->user || ! $accessToken->client) { return $this->invalidTokenResponse('Invalid access token.'); } $clientFields = collect($accessToken->client->allowed_userinfo_fields ?? config('oauth.userinfo_fields', [])) ->map(fn ($field): string => trim((string) $field)) ->filter() ->unique() ->values(); $user = $accessToken->user; $claims = [ 'sub' => (string) $user->id, 'nickname' => (string) ($user->nickname ?? ''), 'email' => (string) ($user->email ?? ''), 'phone' => (string) ($user->phone ?? ''), ]; $payload = ['sub' => $claims['sub']]; foreach ($clientFields as $fieldName) { $field = (string) $fieldName; if ($field === 'sub') { continue; } if (array_key_exists($field, $claims) && $claims[$field] !== '') { $payload[$field] = $claims[$field]; } } $payload = $this->applyClientClaimRemap($payload, collect($accessToken->client->userinfo_claim_remap ?? [])); return response() ->json($payload) ->header('Cache-Control', 'no-store') ->header('Pragma', 'no-cache'); } /** * @param array $payload * @param Collection $remapRules * @return array */ private function applyClientClaimRemap(array $payload, Collection $remapRules): array { foreach ($remapRules as $source => $target) { $from = trim((string) $source); $to = trim((string) $target); if ($from === '' || $to === '' || $from === 'sub' || ! array_key_exists($from, $payload)) { continue; } $payload[$to] = $payload[$from]; unset($payload[$from]); } return $payload; } private function invalidTokenResponse(string $description): JsonResponse { return response() ->json([ 'error' => 'invalid_token', 'error_description' => $description, ], 401) ->header('WWW-Authenticate', 'Bearer error="invalid_token"') ->header('Cache-Control', 'no-store') ->header('Pragma', 'no-cache'); } }