{"record":{"id":"4a2fd420c53058e7","repo":"passbolt/passbolt_api","slug":"the-domain-is-invalid-expected-0-and-got-1","errorCode":null,"errorMessage":"The domain is invalid. Expected: {0} and got {1}","messagePattern":"The domain is invalid\\. Expected: (.+?) and got (.+?)","errorType":"exception","errorClass":"Passbolt\\JwtAuthentication\\Error\\Exception\\Challenge\\InvalidDomainException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/JwtAuthentication/src/Authenticator/GpgJwtAuthenticator.php","lineNumber":450,"sourceCode":"    }\n\n    /**\n     * Assert domain\n     *\n     * @param mixed $domain domain\n     * @return void\n     * @throws \\Passbolt\\JwtAuthentication\\Error\\Exception\\Challenge\\InvalidDomainException if domain is invalid\n     */\n    public function assertDomain(mixed $domain): void\n    {\n        if (!isset($domain) || !is_string($domain)) {\n            throw new InvalidDomainException(__('The domain is invalid.'));\n        }\n\n        if (rtrim($domain, '/') !== rtrim(Router::url('/', true), '/')) {\n            $expect = rtrim(Router::url('/', true));\n            $got = rtrim($domain, '/');\n            throw new InvalidDomainException(__('The domain is invalid. Expected: {0} and got {1}', $expect, $got));\n        }\n    }\n\n    /**\n     * @return \\App\\Utility\\OpenPGP\\OpenPGPBackend\n     */\n    public function getGpg(): OpenPGPBackend\n    {\n        return $this->gpg;\n    }\n\n    /**\n     * @return \\App\\Model\\Entity\\User|null\n     */\n    public function getUser(): ?User\n    {\n        return $this->user;\n    }","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/JwtAuthentication/src/Authenticator/GpgJwtAuthenticator.php#L432-L468","documentation":"Thrown by GpgJwtAuthenticator::assertDomain during GPG-based JWT challenge verification. The client-signed token payload must contain a 'domain' field matching the server's own full base URL. A mismatch means the token was signed for a different host, scheme, or port than the one receiving the request.","triggerScenarios":"A GPG JWT login (POST /auth/jwt/login with an X-GPGAuth token) where the challenge/token 'domain' claim does not equal rtrim(Router::url('/', true), '/').","commonSituations":"Server moved behind a reverse proxy so the computed base URL includes https/host headers the client didn't use; App.fullBaseUrl not set so CakePHP guesses the URL; client configured with http:// instead of https:// or a different hostname (localhost vs 127.0.0.1 vs FQDN); trailing-slash or port mismatches.","solutions":["Set App.fullBaseUrl in config/app.php (or FULL_BASE_URL env) to the exact public URL clients use, e.g. https://passbolt.example.com","Make the client use exactly the same base URL as fullBaseUrl, including scheme and port","Check reverse-proxy headers (X-Forwarded-Proto/Host) so Router::url('/', true) resolves to the public URL","Clear config cache after changing fullBaseUrl: bin/cake cache clear_all"],"exampleFix":"// before (config/app.php)\n// 'fullBaseUrl' => false,\n// after\n'fullBaseUrl' => 'https://passbolt.example.com',","handlingStrategy":"validation","validationCode":"// client-side, before signing\nconst expected = new URL(serverBaseUrl).origin + '/';\nif (!tokenDomain.startsWith(expected)) throw new Error(`domain ${tokenDomain} != ${expected}`);","typeGuard":null,"tryCatchPattern":"try { await passbolt.loginWithGpg(token); } catch (e) { if (String(e.message).includes('The domain is invalid')) { await fixFullBaseUrl(); } else { throw e; } }","preventionTips":["Always set App.fullBaseUrl explicitly to the public URL","Never switch scheme/host behind a proxy without updating fullBaseUrl","Test login after any domain/TLS change"],"tags":["authentication","gpg","jwt","domain-mismatch","config"],"backgroundTag":"invalid-config-value","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}