{"record":{"id":"8e554bd3c70adab0","repo":"BookStackApp/BookStack","slug":"auth-registration-email-domain-invalid","errorCode":null,"errorMessage":"auth.registration_email_domain_invalid","messagePattern":"auth\\.registration_email_domain_invalid","errorType":"exception","errorClass":"UserRegistrationException","httpStatus":null,"severity":"warning","filePath":"app/Access/RegistrationService.php","lineNumber":144,"sourceCode":"     * Ensure that the given email meets any active email domain registration restrictions.\n     * Throws if restrictions are active and the email does not match an allowed domain.\n     *\n     * @throws UserRegistrationException\n     */\n    protected function ensureEmailDomainAllowed(string $userEmail): void\n    {\n        $registrationRestrict = setting('registration-restrict');\n\n        if (!$registrationRestrict) {\n            return;\n        }\n\n        $restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict));\n        $userEmailDomain = mb_substr(mb_strrchr($userEmail, '@'), 1);\n        if (!in_array($userEmailDomain, $restrictedEmailDomains)) {\n            $redirect = $this->registrationAllowed() ? '/register' : '/login';\n\n            throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), $redirect);\n        }\n    }\n}\n","sourceCodeStart":126,"sourceCodeEnd":148,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/RegistrationService.php#L126-L148","documentation":"This UserRegistrationException is thrown by RegistrationService::ensureEmailDomainAllowed when the domain part of the registering user's email is not in the comma-separated 'registration-restrict' setting (Settings > Registration > 'Restrict email domains'). The code extracts everything after the last '@' via mb_strrchr and does a strict in_array comparison against the configured domain list; on mismatch it throws with translated message 'auth.registration_email_domain_invalid' and redirects to /register (if open registration) or /login. Registration is blocked entirely for that email.","triggerScenarios":"setting('registration-restrict') is non-empty (e.g. 'mycompany.com,subsidiary.com') and the submitted email's domain after '@' does not exactly match one of the comma-separated entries — e.g. user emails from 'mail.mycompany.com', a subdomain, different casing rules, or a trailing space/comma typo in the setting, or the email has no '@' (mb_strrchr returns false → substring of garbage).","commonSituations":"Organizations restricting sign-ups to a corporate domain but users registering with a personal Gmail address; admins listing subdomains that don't match (restriction is exact-string, not suffix match); whitespace or case mismatches in the configured list; invited contractors with @partner.example.com addresses while only @example.com is allowed; SAML/OAuth flows where the IdP email uses a different domain than expected.","solutions":["Check Settings > Registration (or the 'registration-restrict' setting in the DB) and ensure the user's email domain exactly matches one entry of the comma-separated list; fix typos, stray spaces, or wrong domains.","If subdomain emails should be allowed, add the subdomain explicitly (e.g. 'example.com,mail.example.com') — the check is exact equality, not suffix-based.","If the user is legitimate and cannot change email, have an admin create the account manually via the Users admin page, which bypasses domain restriction.","If domain restriction is no longer wanted, clear the 'Restrict email domains' field so ensureEmailDomainAllowed returns early.","Consider a theme event (AUTH_PRE_REGISTER) or custom code if you need smarter matching (case-insensitive/suffix) than the built-in exact check."],"exampleFix":"// before (registration-restrict setting)\nexample.com, example.org ,\n\n// after (normalized, includes subdomain actually used)\nexample.com,mail.example.com,example.org","handlingStrategy":"validation","validationCode":"// Mirror the server-side check before submitting registration:\n$restrict = setting('registration-restrict');\nif ($restrict) {\n    $allowed = explode(',', str_replace(' ', '', $restrict));\n    $domain = mb_substr(mb_strrchr($email, '@'), 1);\n    if (!in_array($domain, $allowed, true)) {\n        throw new \\InvalidArgumentException(\"Email domain '{$domain}' is not allowed\");\n    }\n}","typeGuard":null,"tryCatchPattern":"use BookStack\\Exceptions\\UserRegistrationException;\n\ntry {\n    $user = $registrationService->registerUser($userData);\n} catch (UserRegistrationException $e) {\n    if (str_contains($e->getMessage(), 'domain')) {\n        return redirect($e->getRedirect())->withErrors(['email' => trans('auth.registration_email_domain_invalid')]);\n    }\n    throw $e;\n}","preventionTips":["Normalize the registration-restrict list: no stray spaces or trailing commas, consistent lowercase","Remember the match is exact — list every subdomain users actually use","Show allowed domains on the registration form so users pick compliant emails","Periodically audit the setting against real user email domains"],"tags":["php","laravel","registration","validation","access-control"],"backgroundTag":"email-domain-not-allowed","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}