[PM-32480] Add endpoint for Stripe billing portal session#7227
[PM-32480] Add endpoint for Stripe billing portal session#7227cyprain-okeke wants to merge 18 commits intomainfrom
Conversation
|
Great job! No new security vulnerabilities introduced in this pull request |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7227 +/- ##
==========================================
+ Coverage 57.69% 57.73% +0.03%
==========================================
Files 2035 2037 +2
Lines 89672 89738 +66
Branches 7993 7994 +1
==========================================
+ Hits 51738 51809 +71
+ Misses 36074 36070 -4
+ Partials 1860 1859 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| /// </summary> | ||
| [Required] | ||
| [MaxLength(2000)] | ||
| public string? ReturnUrl { get; set; } |
There was a problem hiding this comment.
❓ I don't see this mentioned as a request property in the linked JIRA ticket, or in the tech breakdown. When the mobile client calls this endpoint, what value should this be and where does it come from?
There was a problem hiding this comment.
The ReturnUrl is required by Stripe's billing portal session API (see
https://docs.stripe.com/api/customer_portal/sessions/create). When users finish managing their subscription in the Stripe
portal, they click a "Return to Bitwarden" link that redirects to this URL.
For mobile clients, this should be a deep link (e.g., bitwarden://billing-return or similar app-specific URL scheme) that opens
the app. The mobile client would:
- Open the portal URL in an in-app browser/web view
- After the user completes their session, Stripe redirects to the ReturnUrl
- The deep link triggers the mobile app to close the web view and return to the billing screen
This is standard practice for Stripe portal integration on mobile - the same pattern is used across other platforms (see
https://docs.stripe.com/customer-management/integrate-customer-portal).
| } | ||
|
|
||
| // Prevent open redirect vulnerabilities by restricting to HTTP(S) schemes | ||
| if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps) |
There was a problem hiding this comment.
If ReturnUrl is a deeplink like bitwarden://foo, this validation will trigger an error response. Is that intentional?
There was a problem hiding this comment.
remove the returnurl from the request, instead pass it from the server base on client
|
Overall Assessment: APPROVE Reviewed the new Code Review DetailsNo findings. The implementation is well-aligned with existing billing command patterns and addresses feedback from prior review iterations. |
src/Api/Billing/Controllers/VNext/AccountBillingVNextController.cs
Outdated
Show resolved
Hide resolved
src/Api/Billing/Controllers/VNext/AccountBillingVNextController.cs
Outdated
Show resolved
Hide resolved
src/Core/Billing/Portal/Commands/CreateBillingPortalSessionCommand.cs
Outdated
Show resolved
Hide resolved
src/Core/Billing/Portal/Commands/CreateBillingPortalSessionCommand.cs
Outdated
Show resolved
Hide resolved
src/Core/Billing/Portal/Commands/CreateBillingPortalSessionCommand.cs
Outdated
Show resolved
Hide resolved
src/Core/Billing/Portal/Commands/CreateBillingPortalSessionCommand.cs
Outdated
Show resolved
Hide resolved
src/Core/Billing/Portal/Commands/CreateBillingPortalSessionCommand.cs
Outdated
Show resolved
Hide resolved
src/Core/Billing/Portal/Commands/CreateBillingPortalSessionCommand.cs
Outdated
Show resolved
Hide resolved
test/Api.Test/Billing/Controllers/VNext/AccountBillingVNextControllerTests.cs
Show resolved
Hide resolved
test/Api.Test/Billing/Controllers/VNext/AccountBillingVNextControllerTests.cs
Show resolved
Hide resolved
test/Core.Test/Billing/Portal/Commands/CreateBillingPortalSessionCommandTests.cs
Outdated
Show resolved
Hide resolved
|




🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-32480
📔 Objective
POST /account/billing/vnext/portal-sessionendpoint that returns a Stripe Customer Portal URLChanges
API Layer
CreatePortalSessionAsyncendpoint toAccountBillingVNextControllerPortalSessionRequestmodel with URL validation and XSS preventionPortalSessionResponsemodel for returning the portal URLCore Layer
ICreateBillingPortalSessionCommandwith comprehensive business logic validation:activeorpast_dueallowed)CreateBillingPortalSessionAsynctoIStripeAdapterandStripeAdapterTest Plan
📸 Screenshots