{"record":{"id":"8fbaa598f58ff838","repo":"bitwarden/server","slug":"you-do-not-have-permission-to-update-this-connecti","errorCode":null,"errorMessage":"You do not have permission to update this connection.","messagePattern":"You do not have permission to update this connection\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/AdminConsole/Controllers/OrganizationConnectionsController.cs","lineNumber":94,"sourceCode":"    }\n\n    [HttpPut(\"{organizationConnectionId}\")]\n    public async Task<OrganizationConnectionResponseModel> UpdateConnection(Guid organizationConnectionId, [FromBody] OrganizationConnectionRequestModel model)\n    {\n        if (model == null)\n        {\n            throw new NotFoundException();\n        }\n\n        var existingOrganizationConnection = await _organizationConnectionRepository.GetByIdOrganizationIdAsync(organizationConnectionId, model.OrganizationId);\n        if (existingOrganizationConnection == null)\n        {\n            throw new NotFoundException();\n        }\n\n        if (!await HasPermissionAsync(existingOrganizationConnection.OrganizationId, existingOrganizationConnection.Type))\n        {\n            throw new BadRequestException(\"You do not have permission to update this connection.\");\n        }\n\n        if (model.Type != existingOrganizationConnection.Type)\n        {\n            throw new BadRequestException(\"The connection type cannot be changed.\");\n        }\n\n        if (await HasConnectionTypeAsync(model, organizationConnectionId, model.Type))\n        {\n            throw new BadRequestException($\"The requested organization already has a connection of type {model.Type}. Only one of each connection type may exist per organization.\");\n        }\n\n        switch (model.Type)\n        {\n            case OrganizationConnectionType.CloudBillingSync:\n                return await CreateOrUpdateOrganizationConnectionAsync<BillingSyncConfig>(organizationConnectionId, model, ValidateBillingSyncConfig);\n            case OrganizationConnectionType.Scim:\n                return await CreateOrUpdateOrganizationConnectionAsync<ScimConfig>(organizationConnectionId, model);","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/AdminConsole/Controllers/OrganizationConnectionsController.cs#L76-L112","documentation":"Thrown by UpdateConnection (PUT /organizations/connections/{id}) when HasPermissionAsync returns false against the existing connection's OrganizationId and Type. Crucially, the permission check uses the persisted connection's type (existingOrganizationConnection.Type), not the request body's type, so the claim must match what is stored. Scim requires ManageScim; the default branch requires OrganizationOwner. Maps to HTTP 400.","triggerScenarios":"PUT on a connection the caller lacks rights to: a non-owner editing a CloudBillingSync connection; a user without ManageScim editing a Scim connection; calling as a member of a different organization than the one that owns the connection.","commonSituations":"A demoted former owner still holds a cached id and tries to edit; a custom-scoped API token missing the specific claim for the connection's type; an admin who can read the list but lacks the elevated permission to write.","solutions":["Ensure the calling user holds the permission matching the stored connection type (Owner for CloudBillingSync, ManageScim for Scim).","If the user's role changed, have them re-authenticate so the refreshed token carries the updated claims.","Use an account/API key explicitly granted the needed organization-scoped permission.","Confirm the connection being edited belongs to an organization the caller is a member of."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Permission is checked against the STORED type, not the body\nvar existing = await GetConnectionAsync(connectionId);\nvar neededOwner = existing.Type != OrganizationConnectionType.Scim;\nvar ok = neededOwner\n    ? await currentUser.IsOrganizationOwnerAsync(existing.OrganizationId)\n    : await currentUser.CanManageScimAsync(existing.OrganizationId);\nif (!ok) throw new UnauthorizedAccessException();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Base the permission check on the persisted connection's type, never the request body.","Re-authenticate after role changes so claims refresh.","Use an API key explicitly granted the matching claim."],"tags":["permissions","organization-connections","authorization","http-400"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}