{"record":{"id":"50d106f78a2db02d","repo":"passbolt/passbolt_api","slug":"the-tid-tenant-id-parameter-is-invalid","errorCode":null,"errorMessage":"The tid (tenant id) parameter is invalid.","messagePattern":"The tid \\(tenant id\\) parameter is invalid\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"plugins/PassboltEe/Sso/src/Utility/Azure/OpenId/AzureIdToken.php","lineNumber":51,"sourceCode":"/**\n * @property \\Passbolt\\Sso\\Utility\\Azure\\Provider\\AzureProvider $provider\n */\nclass AzureIdToken extends BaseIdToken\n{\n    /**\n     * {@inheritDoc}\n     *\n     * Override this method to perform provider specific assertions.\n     */\n    public function assertTokenClaims(array $tokenClaims): void\n    {\n        parent::assertTokenClaims($tokenClaims);\n\n        if (\n            !isset($tokenClaims['tid']) || !is_string($tokenClaims['tid']) ||\n            $this->provider->getTenant() != $tokenClaims['tid']\n        ) {\n            throw new BadRequestException('The tid (tenant id) parameter is invalid.');\n        }\n\n        if (\n            !isset($tokenClaims['ver']) || !is_string($tokenClaims['ver']) ||\n            $tokenClaims['ver'] != AzureProvider::ENDPOINT_VERSION_2_0\n        ) {\n            throw new BadRequestException('The ver (version) parameter is invalid.');\n        }\n    }\n}\n","sourceCodeStart":33,"sourceCodeEnd":62,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Utility/Azure/OpenId/AzureIdToken.php#L33-L62","documentation":"AzureIdToken::assertTokenClaims() validates Azure AD-specific ID token claims after generic JWT validation. It requires a string 'tid' claim equal to the configured tenant ID; any mismatch or absence throws BadRequestException, guarding against tokens issued for a different Azure tenant.","triggerScenarios":"An Azure ID token is presented whose 'tid' claim is missing, not a string, or does not equal the tenant configured in the Azure provider settings.","commonSituations":"User authenticating with a personal Microsoft account or a different work tenant than the one configured; multi-tenant app misconfig; tenant ID copy-paste error (wrong GUID) in passbolt SSO settings; token obtained from the v1 endpoint.","solutions":["Verify the tenant ID in passbolt SSO settings matches the 'tid' claim (decode the ID token to check)","Restrict the Azure app to the correct tenant (signInAudience = AzureADMyOrg) or update settings for multi-tenant use","Ensure users sign in with accounts from the configured tenant only","Check you are using the v2.0 endpoint consistently (see related 'ver' check)"],"exampleFix":"// before: tenant GUID mismatch\nConfigure::write('passbolt.security.sso.provider.azureAd.tenantId', 'wrong-guid');\n// after: use Directory (tenant) ID from Azure portal\nConfigure::write('passbolt.security.sso.provider.azureAd.tenantId', '00000000-0000-0000-0000-000000000000');","handlingStrategy":"try-catch","validationCode":"$claims = json_decode(base64_decode(strtr(explode('.', $idToken)[1], '-_', '+/')), true); if (($claims['tid'] ?? null) !== $expectedTenantId) { /* tenant mismatch, stop before verification */ }","typeGuard":"function isExpectedTenant(?string $tid, string $expected): bool { return is_string($tid) && $tid === $expected; }","tryCatchPattern":"try { AzureIdToken::assertTokenClaims($claims); } catch (BadRequestException $e) { return $this->respondError(401, 'ID token was issued for a different tenant.'); }","preventionTips":["Copy the tenant GUID directly from Azure portal into SSO settings","Restrict the Azure app to your tenant","Test with a user from the intended tenant before rollout"],"tags":["sso","azure-ad","jwt","tenant-id","validation"],"backgroundTag":"jwt-claim-validation-failed","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"}