{"record":{"id":"1d83d182a4df4df7","repo":"bitwarden/server","slug":"premium-status-is-required","errorCode":null,"errorMessage":"Premium status is required.","messagePattern":"Premium status is required\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Auth/Controllers/TwoFactorController.cs","lineNumber":563,"sourceCode":"        {\n            throw new UnauthorizedAccessException();\n        }\n\n        if (!TwoFactorUserVerificationTokenable.Validate(\n                _twoFactorUserVerificationDataProtector, userVerificationToken, user, providerType))\n        {\n            throw new BadRequestException(\"UserVerificationToken\", \"User verification failed.\");\n        }\n        return user;\n    }\n\n    /// <summary>Verifies the user has premium access.</summary>\n    /// <exception cref=\"BadRequestException\">User cannot access premium.</exception>\n    private async Task ValidateUserHasPremiumAsync(User user)\n    {\n        if (!await _userService.CanAccessPremium(user))\n        {\n            throw new BadRequestException(\"Premium status is required.\");\n        }\n    }\n\n    /// <summary>Mints a protected user-verification token bound to <paramref name=\"user\"/> and <paramref name=\"providerType\"/>.</summary>\n    private string MintProtectedUserVerificationToken(User user, TwoFactorProviderType providerType)\n    {\n        var token = _twoFactorUserVerificationTokenableFactory.CreateToken(user, providerType);\n        return _twoFactorUserVerificationDataProtector.Protect(token);\n    }\n\n    private async Task ValidateYubiKeyAsync(User user, string name, string value)\n    {\n        if (string.IsNullOrWhiteSpace(value) || value.Length == 12)\n        {\n            return;\n        }\n\n        if (!await _userManager.VerifyTwoFactorTokenAsync(user,","sourceCodeStart":545,"sourceCodeEnd":581,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Auth/Controllers/TwoFactorController.cs#L545-L581","documentation":"BadRequestException 'Premium status is required.' is thrown in ValidateUserHasPremiumAsync when _userService.CanAccessPremium(user) returns false. Certain two-factor providers (Duo) require a premium subscription (directly or via an org with premium); non-premium users are blocked before configuration is saved.","triggerScenarios":"PUT /api/users/two-factor/duo (PutDuo, and other premium-gated flows) called by a user with no active premium subscription and no premium-granting organization membership.","commonSituations":"Free-tier user attempting to enable Duo 2FA, an expired premium subscription, or a premium org whose membership/seat was removed. Self-hosted setups without a valid license also report non-premium.","solutions":["Upgrade the account to premium (or join a premium organization) before enabling Duo.","On self-hosted, verify the installation license is installed and valid.","Confirm the org membership still grants premium (seat not revoked).","If premium was just purchased, allow time for propagation and re-check CanAccessPremium."],"exampleFix":"// before\napi.put('/users/two-factor/duo', { ... }) // free account\n// after\nawait billingService.upgradeToPremium();\napi.put('/users/two-factor/duo', { ... });","handlingStrategy":"validation","validationCode":"const premium = await billingService.canAccessPremium();\nif (!premium) throw new Error('Premium required for Duo two-factor');","typeGuard":null,"tryCatchPattern":"try { await api.put('/users/two-factor/duo', model); }\ncatch (e) {\n  if (e.response?.status === 400 && /Premium status is required/.test(e.response.data?.message)) {\n    throw new UserFacingError('Upgrade to premium to enable Duo 2FA.');\n  }\n  throw e;\n}","preventionTips":["Check premium status before offering Duo as a 2FA option.","On self-hosted, install a valid license.","Re-check premium after org membership changes."],"tags":["two-factor","premium","duo","billing"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}