bitwarden/server · error · UnauthorizedAccessException

Unauthorized.

Error message

Unauthorized.

What it means

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.

Source

Thrown at src/Api/AdminConsole/Controllers/OrganizationDomainController.cs:145

    [AllowAnonymous]
    [HttpPost("domain/sso/verified")]
    public async Task<VerifiedOrganizationDomainSsoDetailsResponseModel> GetVerifiedOrgDomainSsoDetailsAsync(
        [FromBody] OrganizationDomainSsoDetailsRequestModel model)
    {
        var ssoResults = (await _organizationDomainRepository
            .GetVerifiedOrganizationDomainSsoDetailsAsync(model.Email))
            .ToList();

        return new VerifiedOrganizationDomainSsoDetailsResponseModel(
            ssoResults.Select(ssoResult => new VerifiedOrganizationDomainSsoDetailResponseModel(ssoResult)));
    }

    private async Task ValidateOrganizationAccessAsync(Guid orgIdGuid)
    {
        if (!await _currentContext.ManageSso(orgIdGuid))
        {
            throw new UnauthorizedAccessException();
        }

        var organization = await _organizationRepository.GetByIdAsync(orgIdGuid);
        if (organization == null)
        {
            throw new NotFoundException();
        }
    }
}

View on GitHub (pinned to e93b962371)

Solutions

  1. Ensure the calling user has the Manage SSO permission for the target organization (typically an Owner / SSO admin role).
  2. Re-authenticate after a permission change so the token carries updated claims.
  3. Use an API key / service account explicitly granted ManageSso for the org.
  4. Confirm orgId in the route matches an organization the caller can administer.
Defensive patterns

Strategy: validation

Validate before calling

// Confirm Manage SSO before any organization-domain call
if (!await currentUser.CanManageSsoAsync(orgId))
    throw new UnauthorizedAccessException("Caller lacks Manage SSO for this organization.");

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13). Data as JSON: /api/errors/f4da2c650fb2f3b0. Report an issue: GitHub.