web: guard invalid VAPID key during push subscription
This commit is contained in:
@@ -9,7 +9,7 @@ let foregroundListenerAttached = false;
|
|||||||
|
|
||||||
export async function ensureWebPushRegistration(): Promise<void> {
|
export async function ensureWebPushRegistration(): Promise<void> {
|
||||||
const config = getFirebaseConfig();
|
const config = getFirebaseConfig();
|
||||||
const vapidKey = import.meta.env.VITE_FIREBASE_VAPID_KEY?.trim();
|
const vapidKey = normalizeVapidKey(import.meta.env.VITE_FIREBASE_VAPID_KEY);
|
||||||
if (!config || !vapidKey) {
|
if (!config || !vapidKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -33,10 +33,21 @@ export async function ensureWebPushRegistration(): Promise<void> {
|
|||||||
const registration = await navigator.serviceWorker.ready;
|
const registration = await navigator.serviceWorker.ready;
|
||||||
const app = getApps()[0] ?? initializeApp(config);
|
const app = getApps()[0] ?? initializeApp(config);
|
||||||
const messaging = getMessaging(app);
|
const messaging = getMessaging(app);
|
||||||
const token = await getToken(messaging, {
|
let token: string | null = null;
|
||||||
vapidKey,
|
try {
|
||||||
serviceWorkerRegistration: registration,
|
token = await getToken(messaging, {
|
||||||
});
|
vapidKey,
|
||||||
|
serviceWorkerRegistration: registration,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof DOMException && error.name === "InvalidAccessError") {
|
||||||
|
console.error(
|
||||||
|
"[web-push] Invalid VAPID key format. Check VITE_FIREBASE_VAPID_KEY in web env.",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -107,3 +118,34 @@ function getFirebaseConfig():
|
|||||||
appId,
|
appId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeVapidKey(raw: string | undefined): string | null {
|
||||||
|
if (!raw) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let key = raw.trim();
|
||||||
|
if (!key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept accidental JSON payloads copied from docs/panels.
|
||||||
|
if (key.startsWith("{") && key.endsWith("}")) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(key) as { vapidKey?: string; publicKey?: string; key?: string };
|
||||||
|
key = (parsed.vapidKey ?? parsed.publicKey ?? parsed.key ?? "").trim();
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip wrapping quotes and whitespace/newlines.
|
||||||
|
key = key.replace(/^['"]|['"]$/g, "").replace(/\s+/g, "");
|
||||||
|
|
||||||
|
// Convert classic base64 chars to URL-safe format expected by PushManager/Firebase.
|
||||||
|
key = key.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
||||||
|
|
||||||
|
if (!/^[A-Za-z0-9\-_]+$/.test(key)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return key.length >= 80 ? key : null;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user