{"record":{"id":"53ab7e37e4c9b8b3","repo":"bitwarden/server","slug":"resource-not-found-53ab7e","errorCode":null,"errorMessage":"Resource not found.","messagePattern":"Resource not found\\.","errorType":"exception","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"src/Api/Dirt/Controllers/OrganizationIntegrationConfigurationController.cs","lineNumber":27,"sourceCode":"namespace Bit.Api.Dirt.Controllers;\n\n[Route(\"organizations/{organizationId:guid}/integrations/{integrationId:guid}/configurations\")]\n[Authorize(\"Application\")]\npublic class OrganizationIntegrationConfigurationController(\n    ICurrentContext currentContext,\n    ICreateOrganizationIntegrationConfigurationCommand createCommand,\n    IUpdateOrganizationIntegrationConfigurationCommand updateCommand,\n    IDeleteOrganizationIntegrationConfigurationCommand deleteCommand,\n    IGetOrganizationIntegrationConfigurationsQuery getQuery) : Controller\n{\n    [HttpGet(\"\")]\n    public async Task<List<OrganizationIntegrationConfigurationResponseModel>> GetAsync(\n        Guid organizationId,\n        Guid integrationId)\n    {\n        if (!await HasPermission(organizationId))\n        {\n            throw new NotFoundException();\n        }\n\n        var configurations = await getQuery.GetManyByIntegrationAsync(organizationId, integrationId);\n        return configurations\n            .Select(configuration => new OrganizationIntegrationConfigurationResponseModel(configuration))\n            .ToList();\n    }\n\n    [HttpPost(\"\")]\n    public async Task<OrganizationIntegrationConfigurationResponseModel> CreateAsync(\n        Guid organizationId,\n        Guid integrationId,\n        [FromBody] OrganizationIntegrationConfigurationRequestModel model)\n    {\n        if (!await HasPermission(organizationId))\n        {\n            throw new NotFoundException();\n        }","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Dirt/Controllers/OrganizationIntegrationConfigurationController.cs#L9-L45","documentation":"Thrown by GET /organizations/{organizationId}/integrations/{integrationId}/configurations when the caller is not an owner of the organization. HasPermission delegates to currentContext.OrganizationOwner(organizationId); failure is reported as a generic NotFoundException (HTTP 404) rather than 403, to avoid leaking the existence of integration configurations to unauthorized users.","triggerScenarios":"Any authenticated user who is NOT an organization owner calls the GET configurations endpoint — e.g. an admin, a custom-role user, or a manager. Also fires for a user who was removed from the org but still holds a valid session token.","commonSituations":"Calling the endpoint with a service account or API key that lacks the Owner role; testing with a non-owner user account; org membership recently revoked but client still cached the session.","solutions":["Call the endpoint as a user who holds the Owner role on the target organization.","If using an API token / service account, ensure it is scoped to an owner-level principal or re-issue the call from an owner account.","Confirm the organizationId in the path is the org the caller actually owns — a stale/wrong org id will always fail this check."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Client-side: only show the configurations UI when the user is an owner\nvar me = await GetCurrentUserAsync();\nvar isOwner = await IsOrgOwnerAsync(me.Id, organizationId);\nif (!isOwner) { /* hide/disable the configurations call */ }","typeGuard":null,"tryCatchPattern":"try { var cfgs = await client.GetAsync($\"/organizations/{orgId}/integrations/{intId}/configurations\"); }\ncatch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)\n{ /* either no configs or not an owner — treat as 'not available' */ }","preventionTips":["Gate the configurations UI/actions behind an owner-role check in the client.","Prefer owner-scoped credentials for any automation touching integration configs.","Treat 404 from this endpoint as 'not authorized or empty' rather than a hard error."],"tags":["authorization","rbac","organization-owner","aspnetcore","csharp"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}