40 lines
1.6 KiB
PHP
40 lines
1.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
final class UrlValidator
|
|
{
|
|
public static function assertSafeRedirectPath(string $path): string
|
|
{
|
|
$path = trim($path);
|
|
if ($path === '' || !str_starts_with($path, '/') || str_starts_with($path, '//') || str_contains($path, '\\')) {
|
|
throw new InvalidArgumentException('Invalid redirect path');
|
|
}
|
|
if (!preg_match('/^\/[A-Za-z0-9._~%\/?=+-]*$/', $path)) {
|
|
throw new InvalidArgumentException('Invalid redirect path');
|
|
}
|
|
if (preg_match('/^[a-z][a-z0-9+.-]*:\/\//i', $path)) {
|
|
throw new InvalidArgumentException('Invalid redirect path');
|
|
}
|
|
return $path;
|
|
}
|
|
|
|
public static function assertGeneratedLoginUrl(string $url, Settings $settings): string
|
|
{
|
|
$parts = parse_url($url);
|
|
$base = parse_url($settings->targetBaseUrl());
|
|
if (!is_array($parts) || !is_array($base)) {
|
|
throw new InvalidArgumentException('Invalid login URL');
|
|
}
|
|
$scheme = strtolower((string)($parts['scheme'] ?? ''));
|
|
$host = strtolower((string)($parts['host'] ?? ''));
|
|
$baseHost = strtolower((string)($base['host'] ?? ''));
|
|
$port = (int)($parts['port'] ?? ($scheme === 'https' ? 443 : 80));
|
|
$basePort = (int)($base['port'] ?? 443);
|
|
parse_str((string)($parts['query'] ?? ''), $query);
|
|
if ($scheme !== 'https' || $host !== $baseHost || $port !== $basePort || ($parts['path'] ?? '') !== '/api/login/url' || empty($query['key'])) {
|
|
throw new InvalidArgumentException('Invalid login URL');
|
|
}
|
|
return $url;
|
|
}
|
|
}
|