diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index b85bdc0133..27067c3a0e 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -45,6 +45,7 @@ use Appwrite\Auth\Validator\PasswordHistory; use Appwrite\Auth\Validator\PasswordDictionary; use Appwrite\Auth\Validator\PersonalData; use Appwrite\Event\Messaging; +use Utopia\Validator\Hostname; $oauthDefaultSuccess = '/auth/oauth2/success'; $oauthDefaultFailure = '/auth/oauth2/failure'; @@ -315,8 +316,8 @@ App::get('/v1/account/sessions/oauth2/:provider') ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') ->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('oAuthProviders'), fn($node) => (!$node['mock'])))) . '.') - ->param('success', '', fn($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) - ->param('failure', '', fn($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('success', '', fn($clients) => new Hostname($clients), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('failure', '', fn($clients) => new Hostname($clients), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) ->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('request') ->inject('response') @@ -925,7 +926,7 @@ App::post('/v1/account/sessions/magic-url') ->label('abuse-key', 'url:{url},email:{param-email}') ->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') - ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('url', '', fn($clients) => new Hostname($clients), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) ->inject('request') ->inject('response') ->inject('user') @@ -2553,7 +2554,7 @@ App::post('/v1/account/recovery') ->label('abuse-limit', 10) ->label('abuse-key', ['url:{url},email:{param-email}', 'ip:{ip}']) ->param('email', '', new Email(), 'User email.') - ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) + ->param('url', '', fn ($clients) => new Hostname($clients), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) ->inject('request') ->inject('response') ->inject('user') @@ -2817,7 +2818,7 @@ App::post('/v1/account/verification') ->label('sdk.response.model', Response::MODEL_TOKEN) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') - ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page + ->param('url', '', fn($clients) => new Hostname($clients), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page ->inject('request') ->inject('response') ->inject('project') diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 65a0520d1c..d75d5768da 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -23,6 +23,7 @@ use Utopia\Migration\Sources\NHost; use Utopia\Migration\Sources\Supabase; use Utopia\Validator\ArrayList; use Utopia\Validator\Host; +use Utopia\Validator\Hostname; use Utopia\Validator\Integer; use Utopia\Validator\Text; use Utopia\Validator\URL; @@ -631,7 +632,7 @@ App::get('/v1/migrations/firebase/connect') ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) ->label('sdk.methodType', 'webAuth') ->label('sdk.hide', true) - ->param('redirect', '', fn ($clients) => new Host($clients), 'URL to redirect back to your Firebase authorization. Only console hostnames are allowed.', true, ['clients']) + ->param('redirect', '', fn ($clients) => new Hostname($clients), 'URL to redirect back to your Firebase authorization. Only console hostnames are allowed.', true, ['clients']) ->param('projectId', '', new UID(), 'Project ID') ->inject('response') ->inject('request') diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 2ba27efcb3..4ec5ee2f2c 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -38,6 +38,7 @@ use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; +use Utopia\Validator\Hostname; use Utopia\Validator\Text; App::post('/v1/teams') @@ -378,7 +379,7 @@ App::post('/v1/teams/:teamId/memberships') ->param('userId', '', new UID(), 'ID of the user to be added to a team.', true) ->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.') - ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) // TODO add our own built-in confirm page + ->param('url', '', fn($clients) => new Hostname($clients), 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) // TODO add our own built-in confirm page ->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true) ->inject('response') ->inject('project') diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 1b0c993e11..c7e00cccdc 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -35,6 +35,7 @@ use Utopia\Detector\Adapter\Ruby; use Utopia\Detector\Adapter\Swift; use Utopia\Detector\Detector; use Utopia\Validator\Boolean; +use Utopia\Validator\Hostname; use Utopia\VCS\Exception\RepositoryNotFound; use function Swoole\Coroutine\batch; @@ -259,8 +260,8 @@ App::get('/v1/vcs/github/authorize') ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) ->label('sdk.methodType', 'webAuth') ->label('sdk.hide', true) - ->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to console after a successful installation attempt.', true, ['clients']) - ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to console after a failed installation attempt.', true, ['clients']) + ->param('success', '', fn ($clients) => new Hostname($clients), 'URL to redirect back to console after a successful installation attempt.', true, ['clients']) + ->param('failure', '', fn ($clients) => new Hostname($clients), 'URL to redirect back to console after a failed installation attempt.', true, ['clients']) ->inject('request') ->inject('response') ->inject('project') diff --git a/app/controllers/mock.php b/app/controllers/mock.php index fc168ead26..5cf0ba5105 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -16,6 +16,7 @@ use Utopia\Database\Validator\UID; use Utopia\VCS\Adapter\Git\GitHub; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Validator\Hostname; App::get('/v1/mock/tests/general/oauth2') ->desc('OAuth Login') @@ -24,7 +25,7 @@ App::get('/v1/mock/tests/general/oauth2') ->label('docs', false) ->label('sdk.mock', true) ->param('client_id', '', new Text(100), 'OAuth2 Client ID.') - ->param('redirect_uri', '', new Host(['localhost']), 'OAuth2 Redirect URI.') // Important to deny an open redirect attack + ->param('redirect_uri', '', new Hostname(['localhost']), 'OAuth2 Redirect URI.') // Important to deny an open redirect attack ->param('scope', '', new Text(100), 'OAuth2 scope list.') ->param('state', '', new Text(1024), 'OAuth2 state.') ->inject('response') @@ -42,7 +43,7 @@ App::get('/v1/mock/tests/general/oauth2/token') ->param('client_id', '', new Text(100), 'OAuth2 Client ID.') ->param('client_secret', '', new Text(100), 'OAuth2 scope list.') ->param('grant_type', 'authorization_code', new WhiteList(['refresh_token', 'authorization_code']), 'OAuth2 Grant Type.', true) - ->param('redirect_uri', '', new Host(['localhost']), 'OAuth2 Redirect URI.', true) + ->param('redirect_uri', '', new Hostname(['localhost']), 'OAuth2 Redirect URI.', true) ->param('code', '', new Text(100), 'OAuth2 state.', true) ->param('refresh_token', '', new Text(100), 'OAuth2 refresh token.', true) ->inject('response')