{"record":{"id":"f4da2c650fb2f3b0","repo":"bitwarden/server","slug":"unauthorized-f4da2c","errorCode":null,"errorMessage":"Unauthorized.","messagePattern":"Unauthorized\\.","errorType":"http","errorClass":"UnauthorizedAccessException","httpStatus":401,"severity":"error","filePath":"src/Api/AdminConsole/Controllers/OrganizationDomainController.cs","lineNumber":145,"sourceCode":"\n    [AllowAnonymous]\n    [HttpPost(\"domain/sso/verified\")]\n    public async Task<VerifiedOrganizationDomainSsoDetailsResponseModel> GetVerifiedOrgDomainSsoDetailsAsync(\n        [FromBody] OrganizationDomainSsoDetailsRequestModel model)\n    {\n        var ssoResults = (await _organizationDomainRepository\n            .GetVerifiedOrganizationDomainSsoDetailsAsync(model.Email))\n            .ToList();\n\n        return new VerifiedOrganizationDomainSsoDetailsResponseModel(\n            ssoResults.Select(ssoResult => new VerifiedOrganizationDomainSsoDetailResponseModel(ssoResult)));\n    }\n\n    private async Task ValidateOrganizationAccessAsync(Guid orgIdGuid)\n    {\n        if (!await _currentContext.ManageSso(orgIdGuid))\n        {\n            throw new UnauthorizedAccessException();\n        }\n\n        var organization = await _organizationRepository.GetByIdAsync(orgIdGuid);\n        if (organization == null)\n        {\n            throw new NotFoundException();\n        }\n    }\n}\n","sourceCodeStart":127,"sourceCodeEnd":155,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/AdminConsole/Controllers/OrganizationDomainController.cs#L127-L155","documentation":"Thrown as UnauthorizedAccessException by ValidateOrganizationAccessAsync, the shared guard for OrganizationDomainController endpoints (Get/GetAll/Post/Verify/RemoveDomain). It fires when _currentContext.ManageSso(orgIdGuid) returns false — the authenticated user lacks the Manage SSO permission for that organization. This is the first check; the org-existence check (NotFoundException) only runs after this passes. Maps to HTTP 401.","triggerScenarios":"Any organization-domain endpoint (GET/POST/DELETE /organizations/{orgId}/domain/...) called by a user without the ManageSso claim for that org; calling as a non-admin member; calling with a token scoped to a different org.","commonSituations":"A standard org member (not an SSO admin/owner) trying to manage custom domains; an API token without the SSO scope; a user whose ManageSso was revoked but who still holds a valid session token; cross-tenant request with the wrong orgId.","solutions":["Ensure the calling user has the Manage SSO permission for the target organization (typically an Owner / SSO admin role).","Re-authenticate after a permission change so the token carries updated claims.","Use an API key / service account explicitly granted ManageSso for the org.","Confirm orgId in the route matches an organization the caller can administer."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm Manage SSO before any organization-domain call\nif (!await currentUser.CanManageSsoAsync(orgId))\n    throw new UnauthorizedAccessException(\"Caller lacks Manage SSO for this organization.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Gate all organization-domain calls behind a ManageSso check resolved from trusted context.","Re-authenticate after permission changes so claims refresh.","Confirm orgId matches an org the caller can administer.","Use an API key explicitly granted Manage SSO."],"tags":["permissions","organization-domain","sso","authorization","http-401"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}