diff --git a/Dockerfile b/Dockerfile index 33393a0c..0ef337e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -93,6 +93,8 @@ ARG NEXT_PUBLIC_4NK_IFRAME_URL ARG NEXT_PUBLIC_API_URL ARG NEXT_PUBLIC_DEFAULT_VALIDATOR_ID ARG NEXT_PUBLIC_DEFAULT_STORAGE_URLS +ARG NEXT_PUBLIC_BACK_BASE +ARG NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED ENV NEXT_PUBLIC_BACK_API_PROTOCOL=${NEXT_PUBLIC_BACK_API_PROTOCOL} \ NEXT_PUBLIC_BACK_API_HOST=${NEXT_PUBLIC_BACK_API_HOST} \ @@ -112,7 +114,9 @@ ENV NEXT_PUBLIC_BACK_API_PROTOCOL=${NEXT_PUBLIC_BACK_API_PROTOCOL} \ NEXT_PUBLIC_4NK_IFRAME_URL=${NEXT_PUBLIC_4NK_IFRAME_URL} \ NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} \ NEXT_PUBLIC_DEFAULT_VALIDATOR_ID=${NEXT_PUBLIC_DEFAULT_VALIDATOR_ID} \ - NEXT_PUBLIC_DEFAULT_STORAGE_URLS=${NEXT_PUBLIC_DEFAULT_STORAGE_URLS} + NEXT_PUBLIC_DEFAULT_STORAGE_URLS=${NEXT_PUBLIC_DEFAULT_STORAGE_URLS} \ + NEXT_PUBLIC_BACK_BASE=${NEXT_PUBLIC_BACK_BASE} \ + NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED=${NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED} RUN --mount=type=cache,target=/leCoffre-front/.next/cache npm run build @@ -153,6 +157,8 @@ ARG NEXT_PUBLIC_4NK_IFRAME_URL ARG NEXT_PUBLIC_API_URL ARG NEXT_PUBLIC_DEFAULT_VALIDATOR_ID ARG NEXT_PUBLIC_DEFAULT_STORAGE_URLS +ARG NEXT_PUBLIC_BACK_BASE +ARG NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED ENV NODE_ENV=production \ PORT=3000 \ @@ -174,7 +180,9 @@ ENV NODE_ENV=production \ NEXT_PUBLIC_4NK_IFRAME_URL=${NEXT_PUBLIC_4NK_IFRAME_URL} \ NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} \ NEXT_PUBLIC_DEFAULT_VALIDATOR_ID=${NEXT_PUBLIC_DEFAULT_VALIDATOR_ID} \ - NEXT_PUBLIC_DEFAULT_STORAGE_URLS=${NEXT_PUBLIC_DEFAULT_STORAGE_URLS} + NEXT_PUBLIC_DEFAULT_STORAGE_URLS=${NEXT_PUBLIC_DEFAULT_STORAGE_URLS} \ + NEXT_PUBLIC_BACK_BASE=${NEXT_PUBLIC_BACK_BASE} \ + NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED=${NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED} # Next.js standalone runtime (output: 'standalone') COPY --from=builder /leCoffre-front/.next/standalone ./ diff --git a/backups/nginx/dev4.4nkweb.com-http.conf b/backups/nginx/dev4.4nkweb.com-http.conf new file mode 100644 index 00000000..804d8a0d --- /dev/null +++ b/backups/nginx/dev4.4nkweb.com-http.conf @@ -0,0 +1,15 @@ +# HTTP server for ACME and redirect to HTTPS +server { + listen 80; + server_name dev4.4nkweb.com; + + # ACME HTTP-01 challenges + location /.well-known/acme-challenge/ { + root /var/www/letsencrypt; + } + + # Redirection vers HTTPS pour toutes les autres requêtes + location / { + return 301 https://$server_name$request_uri; + } +} diff --git a/backups/nginx/dev4.4nkweb.com-https.conf b/backups/nginx/dev4.4nkweb.com-https.conf new file mode 100755 index 00000000..8417f1e7 --- /dev/null +++ b/backups/nginx/dev4.4nkweb.com-https.conf @@ -0,0 +1,221 @@ +# Configuration HTTPS pour dev4.4nkweb.com +server { + listen 443 ssl http2; + server_name dev4.4nkweb.com; + + # Certificats SSL + ssl_certificate /etc/letsencrypt/live/dev4.4nkweb.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/dev4.4nkweb.com/privkey.pem; + + # Configuration SSL + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + # Headers de sécurité + add_header Strict-Transport-Security "max-age=63072000" always; + add_header X-Frame-Options DENY always; + add_header X-Content-Type-Options nosniff always; + add_header X-XSS-Protection "1; mode=block" always; + + # Grafana - Interface de monitoring (DOIT être avant location /) + location /grafana/ { + proxy_pass http://localhost:3005/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Configuration spécifique pour Grafana + proxy_set_header X-Grafana-Org-Id 1; + + # Support des WebSockets pour les live updates + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Timeouts + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # Buffer settings + proxy_buffering off; + proxy_request_buffering off; + } + + # Loki API - API de logs (DOIT être avant location /) + location /loki/ { + proxy_pass http://localhost:3100/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # CORS pour les requêtes depuis Grafana + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; + add_header Access-Control-Allow-Headers "Content-Type, Authorization"; + + if ($request_method = 'OPTIONS') { + return 204; + } + } + + # Page de statut des services (DOIT être avant location /) + location /status { + # Redirection vers /status/ + return 301 /status/; + } + + location /status/ { + # Serveur statique pour la page HTML + alias /var/www/lecoffre/status/; + index index.html; + try_files $uri $uri/ /status/index.html; + + # Headers de sécurité + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + + # Cache pour les assets statiques + location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ { + expires 1h; + add_header Cache-Control "public, immutable"; + } + } + + # API de statut des services (DOIT être avant location /) + location /status/api { + proxy_pass http://localhost:3006/api; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # CORS pour les requêtes AJAX + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; + add_header Access-Control-Allow-Headers "Content-Type, Authorization"; + + # Timeouts + proxy_connect_timeout 10s; + proxy_send_timeout 10s; + proxy_read_timeout 10s; + + if ($request_method = 'OPTIONS') { + return 204; + } + } + + # API backend - route /back/ vers /api/ du backend + location ~* ^/back/(.*)$ { + proxy_pass http://localhost:8080/api/$1; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Connection ""; + proxy_buffering off; + } + + # API direct - route /api/ vers le backend + # Autorisations CORS dynamiques pour origines connues + set $cors_origin ""; + if ($http_origin ~* ^(http://local\.4nkweb\.com:3000|https://dev4\.4nkweb\.com)$) { + set $cors_origin $http_origin; + } + + location /api/ { + # CORS pour développement local Next.js + proxy_hide_header Access-Control-Allow-Origin; + proxy_hide_header Access-Control-Allow-Credentials; + proxy_hide_header Access-Control-Allow-Headers; + proxy_hide_header Access-Control-Allow-Methods; + + if ($request_method = OPTIONS) { + add_header Access-Control-Allow-Origin $cors_origin always; + add_header Access-Control-Allow-Credentials "true" always; + add_header Access-Control-Allow-Headers "Content-Type, x-session-id, Authorization" always; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always; + return 204; + } + + add_header Access-Control-Allow-Origin $cors_origin always; + add_header Access-Control-Allow-Credentials "true" always; + add_header Access-Control-Allow-Headers "Content-Type, x-session-id, Authorization" always; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always; + + proxy_pass http://dev3.4nkweb.com:8080/api/; + include /etc/nginx/proxy_params; + proxy_read_timeout 300; + proxy_connect_timeout 300; + proxy_send_timeout 300; + } + + # WebSocket relay (sdk_relay) + location /ws/ { + proxy_pass http://localhost:8090/; + proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key; + proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version; + proxy_set_header Sec-WebSocket-Protocol $http_sec_websocket_protocol; + proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 86400; + } + + # API de transfert de fonds + location /api/v1/funds/ { + proxy_pass http://dev3.4nkweb.com:8080/api/v1/funds/; + include /etc/nginx/proxy_params; + proxy_read_timeout 300; + proxy_connect_timeout 300; + proxy_send_timeout 300; + } + + # favicon + location = /favicon.ico { + root /home/debian/lecoffre_node/conf/nginx/assets; + try_files /favicon.ico =404; + } + + # blindbit + location /blindbit/ { + proxy_pass http://localhost:8000/; + include /etc/nginx/proxy_params; + } + + # signer (sdk_signer) avec support WebSocket + + # lecoffre-front - Application LeCoffre + location /lecoffre { + proxy_pass http://localhost:3004; + include /etc/nginx/proxy_params; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 300; + proxy_send_timeout 300; + proxy_connect_timeout 300; + } + + # ihm_client (root) - DOIT être en dernier + location / { + proxy_pass http://localhost:3003; + include /etc/nginx/proxy_params; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 300; + } +} \ No newline at end of file diff --git a/backups/nginx/local.4nkweb.com-3000.conf b/backups/nginx/local.4nkweb.com-3000.conf new file mode 100644 index 00000000..a4ea5113 --- /dev/null +++ b/backups/nginx/local.4nkweb.com-3000.conf @@ -0,0 +1,64 @@ +server { + listen 0.0.0.0:3000; + listen [::]:3000; + server_name local.4nkweb.com; + + # HTTP pur: pas de HTTPS ni HSTS + + # Favicon + location = /favicon.ico { + root /home/debian/lecoffre_node/conf/nginx/assets; + } + + # Compat: callback ID.not sans basePath (toutes variantes et querystring) + location /authorized-client { + proxy_pass http://127.0.0.2:3004/lecoffre/authorized-client; + include /etc/nginx/proxy_params; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto http; + proxy_set_header X-Forwarded-Prefix /lecoffre; + proxy_read_timeout 300; + } + + # Entrée sans slash + location = /lecoffre { + proxy_pass http://127.0.0.2:3004; + include /etc/nginx/proxy_params; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto http; + proxy_set_header X-Forwarded-Prefix /lecoffre; + proxy_read_timeout 300; + } + + # BasePath /lecoffre + location /lecoffre/ { + proxy_pass http://127.0.0.2:3004; + include /etc/nginx/proxy_params; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto http; + proxy_set_header X-Forwarded-Prefix /lecoffre; + proxy_read_timeout 300; + } + + # HMR (si utilisé en local) + location /lecoffre/_next/webpack-hmr { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto http; + proxy_buffering off; + proxy_pass http://127.0.0.2:3004/lecoffre/_next/webpack-hmr; + proxy_read_timeout 600s; + } + + # Assets Next.js + location ~* ^(/_next/static/|/lecoffre/_next/static/|/.+\.(?:css|js|png|jpg|jpeg|gif|svg|ico|webp|woff2?))$ { + expires 7d; + add_header Cache-Control "public, max-age=604800, immutable" always; + proxy_pass http://127.0.0.2:3004$request_uri; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto http; + proxy_read_timeout 300; + } +} diff --git a/backups/nginx/local.4nkweb.com.conf b/backups/nginx/local.4nkweb.com.conf new file mode 100644 index 00000000..fb6b90b7 --- /dev/null +++ b/backups/nginx/local.4nkweb.com.conf @@ -0,0 +1,9 @@ +server { + listen 80; + server_name local.4nkweb.com; + + # HTTP only: pas de redirection HTTPS, pas d'HSTS + location / { + return 302 http://local.4nkweb.com:3000$request_uri; + } +} diff --git a/src/front/Components/Layouts/Login/StepEmail/index.tsx b/src/front/Components/Layouts/Login/StepEmail/index.tsx index 5a534224..7c69564c 100644 --- a/src/front/Components/Layouts/Login/StepEmail/index.tsx +++ b/src/front/Components/Layouts/Login/StepEmail/index.tsx @@ -53,22 +53,24 @@ export default function StepEmail(props: IProps) { const variables = FrontendVariables.getInstance(); try { const nextUrl = typeof window !== 'undefined' ? `${window.location.origin}/authorized-client` : `${variables.FRONT_APP_HOST}/authorized-client`; - const backBase = variables.BACK_BASE || `${variables.BACK_API_PROTOCOL}://${variables.BACK_API_HOST}${variables.BACK_API_PORT ? `:${variables.BACK_API_PORT}` : ''}`; - const stateEndpoint = new URL(`/api/v1/idnot/state`, backBase); - const resp = await fetch(stateEndpoint.toString(), { + let backBase = variables.BACK_BASE || (process.env.NEXT_PUBLIC_BACK_BASE as string) || `${variables.BACK_API_PROTOCOL}://${variables.BACK_API_HOST}${variables.BACK_API_PORT ? `:${variables.BACK_API_PORT}` : ''}`; + if (!backBase || !/^https?:\/\//i.test(backBase)) { + console.warn('[IDNOT] BACK_BASE invalid or missing, falling back to https://dev3.4nkweb.com'); + backBase = 'https://dev3.4nkweb.com'; + } + const stateEndpoint = `${backBase.replace(/\/$/, '')}/api/v1/idnot/state`; + const resp = await fetch(stateEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ next_url: nextUrl }) }); if (!resp.ok) { console.error('[IDNOT] Failed to create state', resp.status); - setIsErrorModalOpen(4); return; } const { state } = await resp.json(); if (!state) { console.warn('[IDNOT] Backend returned empty state'); - setIsErrorModalOpen(4); return; } const fixedRedirect = variables.IDNOT_REDIRECT_URI_FIXED || 'http://local.4nkweb.com:3000/authorized-client'; @@ -79,7 +81,6 @@ export default function StepEmail(props: IProps) { router.push(authorizeUrl); } catch (e) { console.error('[IDNOT] Unexpected error while starting login', e); - setIsErrorModalOpen(4); } }, [router, setIsErrorModalOpen]); @@ -193,26 +194,7 @@ export default function StepEmail(props: IProps) { - -
- - Notre partenaire ID.Not rencontre actuellement un problème technique. Nous vous tiendrons informé de l'évolution. - Pour toute question, contactez-nous à support@lecoffre.io. - - - - Contactez le support - - -
-
+ {/* Outage modal intentionally removed to restore normal API usage */} {/*