[PM-32480] Add endpoint for Stripe billing portal session#7227
[PM-32480] Add endpoint for Stripe billing portal session#7227cyprain-okeke wants to merge 10 commits intomainfrom
Conversation
|
New Issues (1)Checkmarx found the following issues in this Pull Request
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7227 +/- ##
==========================================
+ Coverage 57.50% 57.55% +0.04%
==========================================
Files 2032 2034 +2
Lines 89544 89625 +81
Branches 7960 7961 +1
==========================================
+ Hits 51496 51582 +86
+ Misses 36202 36198 -4
+ Partials 1846 1845 -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
|





🎟️ 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