{"record":{"id":"54e33d1ddbc8be63","repo":"bitwarden/server","slug":"can-only-redeem-sponsorship-for-an-organization-yo","errorCode":null,"errorMessage":"Can only redeem sponsorship for an organization you own.","messagePattern":"Can only redeem sponsorship for an organization you own\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Billing/Controllers/OrganizationSponsorshipsController.cs","lineNumber":190,"sourceCode":"            _logger.LogWarning(\n                \"Sponsorship redemption failed: invalid token. SponsoredOrganizationId={SponsoredOrganizationId}, SponsorshipId={SponsorshipId}\",\n                model.SponsoredOrganizationId,\n                sponsorship?.Id);\n            throw new BadRequestException(\"Failed to parse sponsorship token.\");\n        }\n\n        _logger.LogInformation(\n            \"Sponsorship token validated: SponsorshipId={SponsorshipId}, SponsoringOrganizationId={SponsoringOrganizationId}\",\n            sponsorship.Id,\n            sponsorship.SponsoringOrganizationId);\n\n        if (!await _currentContext.OrganizationOwner(model.SponsoredOrganizationId))\n        {\n            _logger.LogWarning(\n                \"Sponsorship redemption failed: user is not org owner. SponsoredOrganizationId={SponsoredOrganizationId}, SponsorshipId={SponsorshipId}\",\n                model.SponsoredOrganizationId,\n                sponsorship.Id);\n            throw new BadRequestException(\"Can only redeem sponsorship for an organization you own.\");\n        }\n\n        var freeFamiliesSponsorshipPolicy = await _policyQuery.RunAsync(\n            model.SponsoredOrganizationId, PolicyType.FreeFamiliesSponsorshipPolicy);\n\n        if (freeFamiliesSponsorshipPolicy.Enabled)\n        {\n            _logger.LogWarning(\n                \"Sponsorship redemption failed: Free Families sponsorship has been disabled by org admin policy. SponsoredOrganizationId={SponsoredOrganizationId}, SponsorshipId={SponsorshipId}\",\n                model.SponsoredOrganizationId,\n                sponsorship.Id);\n            throw new BadRequestException(\"Free Bitwarden Families sponsorship has been disabled by your organization administrator.\");\n        }\n\n        await _setUpSponsorshipCommand.SetUpSponsorshipAsync(\n            sponsorship,\n            await _organizationRepository.GetByIdAsync(model.SponsoredOrganizationId));\n","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Billing/Controllers/OrganizationSponsorshipsController.cs#L172-L208","documentation":"Thrown (HTTP 400) when _currentContext.OrganizationOwner(model.SponsoredOrganizationId) returns false — the redeeming user is not an Owner of the sponsored organization. Only Owners may apply a sponsorship to their organization; Admins and lower roles are rejected.","triggerScenarios":"A non-owner user (Admin, custom-role, or member) attempts redemption; the user is an owner of a different org; the user was demoted after the token was issued.","commonSituations":"The designated redeemer holds the Admin role but not Owner; user belongs to multiple orgs and targets the wrong one.","solutions":["Have an Owner of the sponsored organization perform the redemption.","Elevate the intended redeemer to the Owner role, then retry.","Confirm the SponsoredOrganizationId in the request matches an org the user owns."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm the current user is an Owner of the sponsored org before attempting redemption.\nconst isOwner = await isOrgOwner(sponsoredOrgId);\nif (!isOwner) throw new Error('Only an organization Owner can redeem a sponsorship');","typeGuard":null,"tryCatchPattern":"try {\n  await redeemSponsorship(model);\n} catch (e) {\n  if (e.isBadRequest && /organization you own/i.test(e.message)) {\n    prompt('Ask an Owner of this organization to redeem the sponsorship.');\n  } else { throw e; }\n}","preventionTips":["Check the user's role on the sponsored org before showing the redeem action.","Route redemption to an Owner account by default.","Validate SponsoredOrganizationId belongs to a org the user owns."],"tags":["billing","sponsorship","authorization","organization","rbac"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}