mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Improve security
This commit is contained in:
@@ -4,35 +4,18 @@ Generate VAPID keys for push notifications
|
|||||||
Run this script to generate new VAPID keys for your application
|
Run this script to generate new VAPID keys for your application
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pywebpush import WebPushException
|
import sys
|
||||||
import base64
|
import base64
|
||||||
import json
|
|
||||||
|
|
||||||
def generate_vapid_keys():
|
|
||||||
"""Generate VAPID keys for push notifications"""
|
|
||||||
try:
|
|
||||||
from cryptography.hazmat.primitives import serialization
|
from cryptography.hazmat.primitives import serialization
|
||||||
from cryptography.hazmat.primitives.asymmetric import ec
|
from cryptography.hazmat.primitives.asymmetric import ec
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
|
||||||
# Generate private key
|
def generate_vapid_keys():
|
||||||
|
"""Generate VAPID keys for push notifications"""
|
||||||
|
try:
|
||||||
private_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
|
private_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
|
||||||
|
|
||||||
# Get public key
|
|
||||||
public_key = private_key.public_key()
|
public_key = private_key.public_key()
|
||||||
|
|
||||||
# Serialize keys
|
|
||||||
private_pem = private_key.private_bytes(
|
|
||||||
encoding=serialization.Encoding.PEM,
|
|
||||||
format=serialization.PrivateFormat.PKCS8,
|
|
||||||
encryption_algorithm=serialization.NoEncryption()
|
|
||||||
)
|
|
||||||
|
|
||||||
public_pem = public_key.public_bytes(
|
|
||||||
encoding=serialization.Encoding.PEM,
|
|
||||||
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
|
||||||
)
|
|
||||||
|
|
||||||
# Convert to base64 for web push
|
# Convert to base64 for web push
|
||||||
private_key_b64 = base64.urlsafe_b64encode(
|
private_key_b64 = base64.urlsafe_b64encode(
|
||||||
private_key.private_bytes(
|
private_key.private_bytes(
|
||||||
@@ -50,23 +33,12 @@ def generate_vapid_keys():
|
|||||||
|
|
||||||
public_key_b64 = base64.urlsafe_b64encode(public_key_raw).decode('utf-8').rstrip('=')
|
public_key_b64 = base64.urlsafe_b64encode(public_key_raw).decode('utf-8').rstrip('=')
|
||||||
|
|
||||||
print("VAPID Keys Generated:")
|
print(f"VAPID_PRIVATE_KEY=\"{private_key_b64}\"")
|
||||||
print("=" * 50)
|
print(f"VAPID_PUBLIC_KEY=\"{public_key_b64}\"")
|
||||||
print(f"Private Key: {private_key_b64}")
|
|
||||||
print(f"Public Key: {public_key_b64}")
|
|
||||||
print("=" * 50)
|
|
||||||
print("\nAdd these to your environment variables:")
|
|
||||||
print(f"VAPID_PRIVATE_KEY={private_key_b64}")
|
|
||||||
print(f"VAPID_PUBLIC_KEY={public_key_b64}")
|
|
||||||
|
|
||||||
return private_key_b64, public_key_b64
|
return private_key_b64, public_key_b64
|
||||||
|
|
||||||
except ImportError:
|
|
||||||
print("Error: cryptography library not found.")
|
|
||||||
print("Install it with: pip install cryptography")
|
|
||||||
return None, None
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error generating VAPID keys: {e}")
|
print(f"Error generating VAPID keys: {e}", file=sys.stderr)
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -10,11 +10,14 @@ logger = logging.getLogger("uvicorn.error")
|
|||||||
|
|
||||||
class PushNotificationService:
|
class PushNotificationService:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# VAPID keys - load from environment variables
|
self.vapid_private_key = os.getenv("VAPID_PRIVATE_KEY")
|
||||||
self.vapid_private_key = os.getenv("VAPID_PRIVATE_KEY", "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghg2CSKiq0KsXXXImE75Z8UAphGBjkpYjUE87zPBmGqKhRANCAATxbNBGMhNl6gLmPL0PAf2YIJCVYX_TZrSqkj7SCqsu5VNMhnDOan6Qc9hEkcTZgvwj286C24SnxfH5CghVMCI6")
|
self.vapid_public_key = os.getenv("VAPID_PUBLIC_KEY")
|
||||||
self.vapid_public_key = os.getenv("VAPID_PUBLIC_KEY", "BPFs0EYyE2XqAuY8vQ8B_ZggkJVhf9NmtKqSPtIKqy7lU0yGcM5qfpBz2ESRxNmC_CPbzoLbhKfF8fkKCFUwIjo")
|
|
||||||
|
if (not self.vapid_public_key) or (not self.vapid_private_key):
|
||||||
|
raise ValueError("VAPID public or private key is None")
|
||||||
|
|
||||||
self.vapid_claims = {
|
self.vapid_claims = {
|
||||||
"sub": "mailto:admin@fromchat.com",
|
"sub": "mailto:support@fromchat.ru",
|
||||||
"aud": "https://fcm.googleapis.com"
|
"aud": "https://fcm.googleapis.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
JWT_SECRET="jwt-secret-change-in-production"
|
|
||||||
@@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
|
|||||||
import { PRODUCT_NAME, API_BASE_URL } from "../../../core/config";
|
import { PRODUCT_NAME, API_BASE_URL } from "../../../core/config";
|
||||||
import type { DialogProps } from "../../../core/types";
|
import type { DialogProps } from "../../../core/types";
|
||||||
import { MaterialDialog } from "../core/Dialog";
|
import { MaterialDialog } from "../core/Dialog";
|
||||||
import { initialize, isSupported, startElectronReceiver, stopElectronReceiver, subscribe, unsubscribe } from "../../../utils/notifications";
|
import { initialize, isSupported, startElectronReceiver, stopElectronReceiver, subscribe, unsubscribe } from "../../../utils/push-notifications";
|
||||||
import { isElectron } from "../../../electron/electron";
|
import { isElectron } from "../../../electron/electron";
|
||||||
import { useAppState } from "../../state";
|
import { useAppState } from "../../state";
|
||||||
import type { Switch } from "mdui/components/switch";
|
import type { Switch } from "mdui/components/switch";
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useRef } from "react";
|
|||||||
import type { TextField } from "mdui/components/text-field";
|
import type { TextField } from "mdui/components/text-field";
|
||||||
import { useAppState } from "../state";
|
import { useAppState } from "../state";
|
||||||
import { MaterialTextField } from "../components/core/TextField";
|
import { MaterialTextField } from "../components/core/TextField";
|
||||||
import { initialize, isSupported, startElectronReceiver, subscribe } from "../../utils/notifications";
|
import { initialize, isSupported, startElectronReceiver, subscribe } from "../../utils/push-notifications";
|
||||||
import { isElectron } from "../../electron/electron";
|
import { isElectron } from "../../electron/electron";
|
||||||
|
|
||||||
export default function LoginScreen() {
|
export default function LoginScreen() {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { DMPanel, type DMPanelData } from "./panels/DMPanel";
|
|||||||
import { getAuthHeaders } from "../auth/api";
|
import { getAuthHeaders } from "../auth/api";
|
||||||
import { restoreKeys } from "../auth/crypto";
|
import { restoreKeys } from "../auth/crypto";
|
||||||
import { API_BASE_URL } from "../core/config";
|
import { API_BASE_URL } from "../core/config";
|
||||||
import { initialize, subscribe, startElectronReceiver, isSupported } from "../utils/notifications";
|
import { initialize, subscribe, startElectronReceiver, isSupported } from "../utils/push-notifications";
|
||||||
import { isElectron } from "../electron/electron";
|
import { isElectron } from "../electron/electron";
|
||||||
|
|
||||||
type Page = "login" | "register" | "chat"
|
type Page = "login" | "register" | "chat"
|
||||||
|
|||||||
+3
-2
@@ -27,8 +27,9 @@
|
|||||||
"preview": "cd deployment && docker compose up --build --watch",
|
"preview": "cd deployment && docker compose up --build --watch",
|
||||||
"preview:clean": "cd deployment && docker compose down -v",
|
"preview:clean": "cd deployment && docker compose down -v",
|
||||||
"clean": "npm run backend:clean && npm run frontend:clean && npm run preview:clean",
|
"clean": "npm run backend:clean && npm run frontend:clean && npm run preview:clean",
|
||||||
"install": "npm run backend:dependencies && cp deployment/.env.example deployment/.env",
|
"install": "npm run backend:dependencies && npm run generate:env",
|
||||||
"prepare": "husky"
|
"prepare": "husky",
|
||||||
|
"generate:env": "echo \"JWT_SECRET=\\\"$(openssl rand -base64 32)\\\"\" > deployment/.env && ./.venv/bin/python3 backend/generate_vapid_keys.py 1>>deployment/.env"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"frontend/build/electron"
|
"frontend/build/electron"
|
||||||
|
|||||||
Reference in New Issue
Block a user