fix csrf mismatch

This commit is contained in:
Codex Agent
2025-12-22 14:33:36 +01:00
parent f9016fb8ab
commit 83712b9a3a
2 changed files with 67 additions and 12 deletions

View File

@@ -36,6 +36,45 @@ const PADDLE_SCRIPT_URL = 'https://cdn.paddle.com/paddle/v2/paddle.js';
const PADDLE_SUPPORTED_LOCALES = ['en', 'de', 'fr', 'es', 'it', 'nl', 'pt', 'sv', 'da', 'fi', 'no'];
const PRIMARY_CTA_STYLES = 'min-w-[200px] disabled:bg-muted disabled:text-muted-foreground disabled:hover:bg-muted disabled:hover:text-muted-foreground';
const getCookieValue = (name: string): string | null => {
if (typeof document === 'undefined') {
return null;
}
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
return match ? decodeURIComponent(match[1]) : null;
};
export function resolveCheckoutCsrfToken(): string {
if (typeof document === 'undefined') {
return '';
}
const metaToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (metaToken && metaToken.length > 0) {
return metaToken;
}
return getCookieValue('XSRF-TOKEN') ?? '';
}
function buildCheckoutHeaders(): HeadersInit {
const csrfToken = resolveCheckoutCsrfToken();
const headers: HeadersInit = {
'Content-Type': 'application/json',
Accept: 'application/json',
};
if (csrfToken) {
headers['X-CSRF-TOKEN'] = csrfToken;
headers['X-XSRF-TOKEN'] = csrfToken;
}
return headers;
}
export function resolvePaddleLocale(rawLocale?: string | null): string {
if (!rawLocale) {
return 'en';
@@ -271,14 +310,9 @@ export const PaymentStep: React.FC = () => {
setAwaitingConfirmation(false);
try {
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '';
const response = await fetch('/checkout/free-activate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'X-CSRF-TOKEN': csrfToken,
},
headers: buildCheckoutHeaders(),
credentials: 'same-origin',
body: JSON.stringify({
package_id: selectedPackage.id,
@@ -349,11 +383,8 @@ export const PaymentStep: React.FC = () => {
const response = await fetch('/paddle/create-checkout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
},
headers: buildCheckoutHeaders(),
credentials: 'same-origin',
body: JSON.stringify({
package_id: selectedPackage.id,
locale: paddleLocale,