better-auth-mercadopago 0.1.9 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +86 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +271 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/security.d.ts +103 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +300 -0
- package/dist/security.js.map +1 -0
- package/dist/server.d.ts +638 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1095 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +294 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/package.json +1 -1
package/dist/security.js
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { APIError } from "better-auth/api";
|
|
3
|
+
/**
|
|
4
|
+
* Verify Mercado Pago webhook signature
|
|
5
|
+
* https://www.mercadopago.com/developers/en/docs/subscriptions/additional-content/security/signature
|
|
6
|
+
*/
|
|
7
|
+
export function verifyWebhookSignature(params) {
|
|
8
|
+
const { xSignature, xRequestId, dataId, secret } = params;
|
|
9
|
+
if (!xSignature || !xRequestId) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
// Parse x-signature header
|
|
13
|
+
// Format: "ts=1234567890,v1=hash"
|
|
14
|
+
const parts = xSignature.split(",");
|
|
15
|
+
const ts = parts.find((p) => p.startsWith("ts="))?.split("=")[1];
|
|
16
|
+
const hash = parts.find((p) => p.startsWith("v1="))?.split("=")[1];
|
|
17
|
+
if (!ts || !hash) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
// Build the manifest (exactly as MP does)
|
|
21
|
+
const manifest = `id:${dataId};request-id:${xRequestId};ts:${ts};`;
|
|
22
|
+
// Create HMAC SHA256
|
|
23
|
+
const hmac = crypto.createHmac("sha256", secret);
|
|
24
|
+
hmac.update(manifest);
|
|
25
|
+
const expectedHash = hmac.digest("hex");
|
|
26
|
+
// Compare hashes (constant-time comparison)
|
|
27
|
+
return crypto.timingSafeEqual(Buffer.from(hash), Buffer.from(expectedHash));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Rate limiting store (in-memory, use Redis in production)
|
|
31
|
+
*/
|
|
32
|
+
class RateLimiter {
|
|
33
|
+
attempts = new Map();
|
|
34
|
+
check(key, maxAttempts, windowMs) {
|
|
35
|
+
const now = Date.now();
|
|
36
|
+
const record = this.attempts.get(key);
|
|
37
|
+
if (!record || now > record.resetAt) {
|
|
38
|
+
this.attempts.set(key, {
|
|
39
|
+
count: 1,
|
|
40
|
+
resetAt: now + windowMs,
|
|
41
|
+
});
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
if (record.count >= maxAttempts) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
record.count++;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
cleanup() {
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
for (const [key, record] of this.attempts.entries()) {
|
|
53
|
+
if (now > record.resetAt) {
|
|
54
|
+
this.attempts.delete(key);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export const rateLimiter = new RateLimiter();
|
|
60
|
+
// Cleanup every 5 minutes
|
|
61
|
+
setInterval(() => rateLimiter.cleanup(), 5 * 60 * 1000);
|
|
62
|
+
/**
|
|
63
|
+
* Validate payment amount to prevent manipulation
|
|
64
|
+
*/
|
|
65
|
+
export function validatePaymentAmount(requestedAmount, mpPaymentAmount, tolerance = 0.01) {
|
|
66
|
+
const diff = Math.abs(requestedAmount - mpPaymentAmount);
|
|
67
|
+
return diff <= tolerance;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Sanitize metadata to prevent injection attacks
|
|
71
|
+
*/
|
|
72
|
+
export function sanitizeMetadata(
|
|
73
|
+
// biome-ignore lint/suspicious/noExplicitAny: <necessary>
|
|
74
|
+
metadata) {
|
|
75
|
+
// biome-ignore lint/suspicious/noExplicitAny: <necessary>
|
|
76
|
+
const sanitized = {};
|
|
77
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
78
|
+
// Prevent prototype pollution
|
|
79
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
// Limit metadata size
|
|
83
|
+
if (typeof value === "string" && value.length > 5000) {
|
|
84
|
+
sanitized[key] = value.substring(0, 5000);
|
|
85
|
+
}
|
|
86
|
+
else if (typeof value === "object" && value !== null) {
|
|
87
|
+
// Recursively sanitize nested objects
|
|
88
|
+
sanitized[key] = sanitizeMetadata(value);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
sanitized[key] = value;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return sanitized;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Validate callback URL to prevent open redirects
|
|
98
|
+
*/
|
|
99
|
+
export function validateCallbackUrl(url, allowedDomains) {
|
|
100
|
+
try {
|
|
101
|
+
const parsed = new URL(url);
|
|
102
|
+
// Only allow HTTPS in production
|
|
103
|
+
if (process.env.NODE_ENV === "production" && parsed.protocol !== "https:") {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
// Check if domain is allowed
|
|
107
|
+
const hostname = parsed.hostname;
|
|
108
|
+
return allowedDomains.some((domain) => {
|
|
109
|
+
if (domain.startsWith("*.")) {
|
|
110
|
+
// Wildcard subdomain
|
|
111
|
+
const baseDomain = domain.substring(2);
|
|
112
|
+
return hostname.endsWith(baseDomain);
|
|
113
|
+
}
|
|
114
|
+
return hostname === domain;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Idempotency key validation
|
|
123
|
+
*/
|
|
124
|
+
export function validateIdempotencyKey(key) {
|
|
125
|
+
// UUID v4 format or custom format
|
|
126
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
127
|
+
const customRegex = /^[a-zA-Z0-9_-]{8,64}$/;
|
|
128
|
+
return uuidRegex.test(key) || customRegex.test(key);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Prevent timing attacks on webhook validation
|
|
132
|
+
*/
|
|
133
|
+
export function secureCompare(a, b) {
|
|
134
|
+
if (a.length !== b.length) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Error codes mapping
|
|
146
|
+
*/
|
|
147
|
+
export const MercadoPagoErrorCodes = {
|
|
148
|
+
// Authentication
|
|
149
|
+
INVALID_API_KEY: "invalid_api_key",
|
|
150
|
+
UNAUTHORIZED: "unauthorized",
|
|
151
|
+
// Payment errors
|
|
152
|
+
INSUFFICIENT_FUNDS: "cc_rejected_insufficient_amount",
|
|
153
|
+
INVALID_CARD: "cc_rejected_bad_filled_card_number",
|
|
154
|
+
CARD_DISABLED: "cc_rejected_card_disabled",
|
|
155
|
+
MAX_ATTEMPTS: "cc_rejected_max_attempts",
|
|
156
|
+
DUPLICATED_PAYMENT: "cc_rejected_duplicated_payment",
|
|
157
|
+
// Subscription errors
|
|
158
|
+
SUBSCRIPTION_NOT_FOUND: "subscription_not_found",
|
|
159
|
+
SUBSCRIPTION_ALREADY_CANCELLED: "subscription_already_cancelled",
|
|
160
|
+
// General
|
|
161
|
+
INVALID_PARAMETER: "invalid_parameter",
|
|
162
|
+
RESOURCE_NOT_FOUND: "resource_not_found",
|
|
163
|
+
INTERNAL_SERVER_ERROR: "internal_server_error",
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Custom error class for Mercado Pago errors
|
|
167
|
+
*/
|
|
168
|
+
export class MercadoPagoError extends Error {
|
|
169
|
+
code;
|
|
170
|
+
message;
|
|
171
|
+
statusCode;
|
|
172
|
+
details;
|
|
173
|
+
constructor(code, message, statusCode = 400,
|
|
174
|
+
// biome-ignore lint/suspicious/noExplicitAny: <necessary>
|
|
175
|
+
details) {
|
|
176
|
+
super(message);
|
|
177
|
+
this.code = code;
|
|
178
|
+
this.message = message;
|
|
179
|
+
this.statusCode = statusCode;
|
|
180
|
+
this.details = details;
|
|
181
|
+
this.name = "MercadoPagoError";
|
|
182
|
+
}
|
|
183
|
+
toAPIError() {
|
|
184
|
+
const errorMap = {
|
|
185
|
+
400: "BAD_REQUEST",
|
|
186
|
+
401: "UNAUTHORIZED",
|
|
187
|
+
403: "FORBIDDEN",
|
|
188
|
+
404: "NOT_FOUND",
|
|
189
|
+
429: "TOO_MANY_REQUESTS",
|
|
190
|
+
500: "INTERNAL_SERVER_ERROR",
|
|
191
|
+
};
|
|
192
|
+
const type = errorMap[this.statusCode] || "BAD_REQUEST";
|
|
193
|
+
return new APIError(type, {
|
|
194
|
+
message: this.message,
|
|
195
|
+
details: this.details,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Handle Mercado Pago API errors
|
|
201
|
+
*/ // biome-ignore lint/suspicious/noExplicitAny: <necessary>
|
|
202
|
+
export function handleMercadoPagoError(error) {
|
|
203
|
+
if (error.status) {
|
|
204
|
+
const mpError = new MercadoPagoError(error.code || "unknown_error", error.message || "An error occurred with Mercado Pago", error.status, error.cause);
|
|
205
|
+
throw mpError.toAPIError();
|
|
206
|
+
}
|
|
207
|
+
throw new APIError("INTERNAL_SERVER_ERROR", {
|
|
208
|
+
message: "Failed to process Mercado Pago request",
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Webhook event types validation
|
|
213
|
+
*/
|
|
214
|
+
export const VALID_WEBHOOK_TOPICS = [
|
|
215
|
+
"payment",
|
|
216
|
+
"merchant_order",
|
|
217
|
+
"subscription_preapproval",
|
|
218
|
+
"subscription_preapproval_plan",
|
|
219
|
+
"subscription_authorized_payment",
|
|
220
|
+
"point_integration_wh",
|
|
221
|
+
"topic_claims_integration_wh",
|
|
222
|
+
"topic_merchant_order_wh",
|
|
223
|
+
"delivery_cancellation",
|
|
224
|
+
];
|
|
225
|
+
export function isValidWebhookTopic(topic) {
|
|
226
|
+
return VALID_WEBHOOK_TOPICS.includes(topic);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Idempotency store (in-memory, use Redis in production)
|
|
230
|
+
*/
|
|
231
|
+
class IdempotencyStore {
|
|
232
|
+
// biome-ignore lint/suspicious/noExplicitAny: <necessary>
|
|
233
|
+
store = new Map();
|
|
234
|
+
// biome-ignore lint/suspicious/noExplicitAny: <necessary>
|
|
235
|
+
get(key) {
|
|
236
|
+
const record = this.store.get(key);
|
|
237
|
+
if (!record || Date.now() > record.expiresAt) {
|
|
238
|
+
this.store.delete(key);
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
return record.result;
|
|
242
|
+
}
|
|
243
|
+
// biome-ignore lint/suspicious/noExplicitAny: <necessary>
|
|
244
|
+
set(key, result, ttlMs = 24 * 60 * 60 * 1000) {
|
|
245
|
+
this.store.set(key, {
|
|
246
|
+
result,
|
|
247
|
+
expiresAt: Date.now() + ttlMs,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
cleanup() {
|
|
251
|
+
const now = Date.now();
|
|
252
|
+
for (const [key, record] of this.store.entries()) {
|
|
253
|
+
if (now > record.expiresAt) {
|
|
254
|
+
this.store.delete(key);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
export const idempotencyStore = new IdempotencyStore();
|
|
260
|
+
// Cleanup every hour
|
|
261
|
+
setInterval(() => idempotencyStore.cleanup(), 60 * 60 * 1000);
|
|
262
|
+
/**
|
|
263
|
+
* CSRF token validation
|
|
264
|
+
*/
|
|
265
|
+
export function validateCSRFToken(token, expectedToken) {
|
|
266
|
+
return secureCompare(token, expectedToken);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Input validation helpers
|
|
270
|
+
*/
|
|
271
|
+
export const ValidationRules = {
|
|
272
|
+
email: (email) => {
|
|
273
|
+
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
274
|
+
return regex.test(email) && email.length <= 255;
|
|
275
|
+
},
|
|
276
|
+
amount: (amount) => {
|
|
277
|
+
return amount > 0 && amount <= 999999999 && !Number.isNaN(amount);
|
|
278
|
+
},
|
|
279
|
+
currency: (currency) => {
|
|
280
|
+
const validCurrencies = [
|
|
281
|
+
"ARS",
|
|
282
|
+
"BRL",
|
|
283
|
+
"CLP",
|
|
284
|
+
"MXN",
|
|
285
|
+
"COP",
|
|
286
|
+
"PEN",
|
|
287
|
+
"UYU",
|
|
288
|
+
"USD",
|
|
289
|
+
];
|
|
290
|
+
return validCurrencies.includes(currency);
|
|
291
|
+
},
|
|
292
|
+
frequency: (frequency) => {
|
|
293
|
+
return frequency > 0 && frequency <= 365 && Number.isInteger(frequency);
|
|
294
|
+
},
|
|
295
|
+
userId: (userId) => {
|
|
296
|
+
// UUID or custom ID format
|
|
297
|
+
return /^[a-zA-Z0-9_-]{1,100}$/.test(userId);
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"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"}
|