<?php

namespace Tests\Feature\Api\V1\FullSurface;

use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;

class ApiOpenRedirectAndReturnUrlContractTest extends FullSurfaceE2EContractCase
{
    public function test_login_and_navigation_routes_do_not_accept_external_return_urls(): void
    {
        $routes = array_slice($this->apiRoutesContainingAny(['login', 'logout', 'auth', 'frontend', 'nav', 'dashboard', 'redirect']), 0, 80);

        foreach ($routes as $route) {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();
            $payload = $this->payloadFor($method, $uri) + [
                'return_url' => 'https://evil.example/phish',
                'redirect' => '//evil.example/phish',
                'next' => 'https://evil.example/phish',
                'next_url' => 'javascript:alert(1)',
                'continue' => 'https://evil.example/continue',
            ];

            $response = $this->requestAs($this->actorFor($uri), $method, $uri, $payload);

            $this->assertControlled($response, $method, $uri);
            $this->assertNoServerError($response, 'open redirect probe at ' . $method . ' ' . $uri);
            $this->assertStringNotContainsString('evil.example', (string) $response->headers->get('Location'));
        }
    }

    public function test_redirect_like_query_parameters_do_not_poison_get_responses(): void
    {
        foreach (array_slice($this->apiRoutes(), 0, 140) as $route) {
            if ($this->primaryMethod($route) !== 'GET') {
                continue;
            }

            $uri = $route->uri();
            $response = $this->requestAs($this->actorFor($uri), 'GET', $uri, [
                'redirect_uri' => 'https://evil.example/oauth',
                'callback' => '//evil.example/callback',
            ]);

            $this->assertControlled($response, 'GET', $uri);
            $this->assertNoServerError($response, 'redirect query probe at GET ' . $uri);
        }
    }
}
