1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-21 12:05:42 +01:00

[AC-1980] Upgrade Stripe.net (#3596)

* Upgrade Stripe.net

* Don't process mismatched version webhooks

* Manually handle API mismatch in Stripe webhook

* Pivot webhook secret off webhook version
This commit is contained in:
Alex Morask 2024-01-31 08:19:29 -05:00 committed by GitHub
parent 02b10abaf8
commit 2ad4bb8a79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 61 additions and 11 deletions

View File

@ -5,7 +5,7 @@ public class BillingSettings
public virtual string JobsKey { get; set; }
public virtual string StripeWebhookKey { get; set; }
public virtual string StripeWebhookSecret { get; set; }
public virtual bool StripeEventParseThrowMismatch { get; set; } = true;
public virtual string StripeWebhookSecret20231016 { get; set; }
public virtual string BitPayWebhookKey { get; set; }
public virtual string AppleWebhookKey { get; set; }
public virtual FreshDeskSettings FreshDesk { get; set; } = new FreshDeskSettings();

View File

@ -1,4 +1,5 @@
using Bit.Billing.Constants;
using Bit.Billing.Models;
using Bit.Billing.Services;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Context;
@ -19,6 +20,7 @@ using Microsoft.Extensions.Options;
using Stripe;
using Customer = Stripe.Customer;
using Event = Stripe.Event;
using JsonSerializer = System.Text.Json.JsonSerializer;
using PaymentMethod = Stripe.PaymentMethod;
using Subscription = Stripe.Subscription;
using Transaction = Bit.Core.Entities.Transaction;
@ -109,9 +111,27 @@ public class StripeController : Controller
using (var sr = new StreamReader(HttpContext.Request.Body))
{
var json = await sr.ReadToEndAsync();
var webhookSecret = PickStripeWebhookSecret(json);
if (string.IsNullOrEmpty(webhookSecret))
{
return new OkResult();
}
parsedEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"],
_billingSettings.StripeWebhookSecret,
throwOnApiVersionMismatch: _billingSettings.StripeEventParseThrowMismatch);
webhookSecret,
throwOnApiVersionMismatch: false);
}
if (StripeConfiguration.ApiVersion != parsedEvent.ApiVersion)
{
_logger.LogWarning(
"Stripe {WebhookType} webhook's API version ({WebhookAPIVersion}) does not match SDK API Version ({SDKAPIVersion})",
parsedEvent.Type,
parsedEvent.ApiVersion,
StripeConfiguration.ApiVersion);
return new OkResult();
}
if (string.IsNullOrWhiteSpace(parsedEvent?.Id))
@ -872,4 +892,25 @@ public class StripeController : Controller
await invoiceService.VoidInvoiceAsync(invoice.Id);
}
}
private string PickStripeWebhookSecret(string webhookBody)
{
var versionContainer = JsonSerializer.Deserialize<StripeWebhookVersionContainer>(webhookBody);
return versionContainer.ApiVersion switch
{
"2023-10-16" => _billingSettings.StripeWebhookSecret20231016,
"2022-08-01" => _billingSettings.StripeWebhookSecret,
_ => HandleDefault(versionContainer.ApiVersion)
};
string HandleDefault(string version)
{
_logger.LogWarning(
"Stripe webhook contained an recognized 'api_version': {ApiVersion}",
version);
return null;
}
}
}

View File

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Bit.Billing.Models;
public class StripeWebhookVersionContainer
{
[JsonPropertyName("api_version")]
public string ApiVersion { get; set; }
}

View File

@ -62,7 +62,7 @@
"jobsKey": "SECRET",
"stripeWebhookKey": "SECRET",
"stripeWebhookSecret": "SECRET",
"stripeEventParseThrowMismatch": true,
"stripeWebhookSecret20231016": "SECRET",
"bitPayWebhookKey": "SECRET",
"appleWebhookKey": "SECRET",
"payPal": {

View File

@ -52,7 +52,7 @@
<PackageReference Include="Serilog.Sinks.SyslogMessages" Version="2.0.9" />
<PackageReference Include="AspNetCoreRateLimit" Version="4.0.2" />
<PackageReference Include="Braintree" Version="5.23.0" />
<PackageReference Include="Stripe.net" Version="40.16.0" />
<PackageReference Include="Stripe.net" Version="43.7.0" />
<PackageReference Include="Otp.NET" Version="1.2.2" />
<PackageReference Include="YubicoDotNetClient" Version="1.2.0" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.25" />

View File

@ -1,7 +1,7 @@
{
"id": "evt_3NvKgBIGBnsLynRr0pJJqudS",
"object": "event",
"api_version": "2022-08-01",
"api_version": "2023-10-16",
"created": 1695909300,
"data": {
"object": {

View File

@ -1,7 +1,7 @@
{
"id": "evt_1NvLMDIGBnsLynRr6oBxebrE",
"object": "event",
"api_version": "2022-08-01",
"api_version": "2023-10-16",
"created": 1695911902,
"data": {
"object": {

View File

@ -2,7 +2,7 @@
"id": "evt_1NvKjSIGBnsLynRrS3MTK4DZ",
"object": "event",
"account": "acct_19smIXIGBnsLynRr",
"api_version": "2022-08-01",
"api_version": "2023-10-16",
"created": 1695909502,
"data": {
"object": {

View File

@ -1,7 +1,7 @@
{
"id": "evt_1NvKzfIGBnsLynRr0SkwrlkE",
"object": "event",
"api_version": "2022-08-01",
"api_version": "2023-10-16",
"created": 1695910506,
"data": {
"object": {

View File

@ -1,7 +1,7 @@
{
"id": "evt_1Nv0w8IGBnsLynRrZoDVI44u",
"object": "event",
"api_version": "2022-08-01",
"api_version": "2023-10-16",
"created": 1695833408,
"data": {
"object": {

View File

@ -1,7 +1,7 @@
{
"id": "evt_1NvKzcIGBnsLynRrPJ3hybkd",
"object": "event",
"api_version": "2022-08-01",
"api_version": "2023-10-16",
"created": 1695910504,
"data": {
"object": {