diff --git a/web/biome.json b/web/biome.json index 348b08e..4925668 100644 --- a/web/biome.json +++ b/web/biome.json @@ -10,7 +10,7 @@ "includes": [ "src/**", "!src/messages", - "!src/paraglide/**/*.js", + "!src/paraglide/**", "!src/routeTree.gen.ts" ] }, diff --git a/web/messages/en.json b/web/messages/en.json index 11ca20e..e606ca2 100644 --- a/web/messages/en.json +++ b/web/messages/en.json @@ -106,6 +106,7 @@ "openid_mfa_redirect_error_missing_args": "Missing code or state in the callback's URL. The provider might not be configured correctly.", "openid_mfa_complete_title": "Authentication Completed", "openid_mfa_complete_subtitle": "You have been successfully authenticated. Please close this window and get back to the Defguard VPN Client", + "openid_generic_error": "OpenID authentication error", "open_desktop_title": "Open the desktop app to continue", "open_desktop_description": "We tried to open the desktop app automatically, but it didn't respond. This can happen if the browser blocks the request or the app didn't start in time.", "open_desktop_button": "Open desktop app", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 024a123..aa5cfef 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -1407,6 +1407,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} + hasBin: true + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -1479,8 +1484,8 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - brace-expansion@1.1.14: - resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==} + brace-expansion@1.1.15: + resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} brace-expansion@5.0.6: resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} @@ -1832,8 +1837,8 @@ packages: debug: optional: true - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} framer-motion@12.38.0: @@ -1941,6 +1946,10 @@ packages: resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} engines: {node: '>= 0.4'} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + hast-util-to-jsx-runtime@2.3.6: resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} @@ -2064,6 +2073,10 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + js-yaml@4.2.0: + resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} + hasBin: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -2838,8 +2851,8 @@ packages: resolution: {integrity: sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==} engines: {node: ^20.17.0 || >=22.9.0} - ws@8.20.1: - resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==} + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3196,7 +3209,7 @@ snapshots: globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.1.1 + js-yaml: 4.2.0 minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -3673,7 +3686,7 @@ snapshots: '@tanstack/devtools-event-bus@0.4.1': dependencies: - ws: 8.20.1 + ws: 8.21.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -4017,12 +4030,14 @@ snapshots: transitivePeerDependencies: - '@swc/helpers' - acorn-jsx@5.3.2(acorn@8.16.0): + acorn-jsx@5.3.2(acorn@8.17.0): dependencies: - acorn: 8.16.0 + acorn: 8.17.0 acorn@8.16.0: {} + acorn@8.17.0: {} + agent-base@6.0.2: dependencies: debug: 4.4.3 @@ -4071,7 +4086,7 @@ snapshots: axios@1.16.1: dependencies: follow-redirects: 1.16.0 - form-data: 4.0.5 + form-data: 4.0.6 https-proxy-agent: 5.0.1 proxy-from-env: 2.1.0 transitivePeerDependencies: @@ -4097,7 +4112,7 @@ snapshots: binary-extensions@2.3.0: {} - brace-expansion@1.1.14: + brace-expansion@1.1.15: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 @@ -4287,7 +4302,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 - hasown: 2.0.3 + hasown: 2.0.4 esbuild@0.27.7: optionalDependencies: @@ -4376,8 +4391,8 @@ snapshots: espree@10.4.0: dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) eslint-visitor-keys: 4.2.1 esprima@4.0.1: {} @@ -4456,12 +4471,12 @@ snapshots: follow-redirects@1.16.0: {} - form-data@4.0.5: + form-data@4.0.6: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 es-set-tostringtag: 2.1.0 - hasown: 2.0.3 + hasown: 2.0.4 mime-types: 2.1.35 framer-motion@12.38.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6): @@ -4562,6 +4577,10 @@ snapshots: dependencies: function-bind: 1.1.2 + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + hast-util-to-jsx-runtime@2.3.6: dependencies: '@types/estree': 1.0.9 @@ -4669,6 +4688,10 @@ snapshots: dependencies: argparse: 2.0.1 + js-yaml@4.2.0: + dependencies: + argparse: 2.0.1 + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -4978,7 +5001,7 @@ snapshots: minimatch@3.1.5: dependencies: - brace-expansion: 1.1.14 + brace-expansion: 1.1.15 motion-dom@12.38.0: dependencies: @@ -5622,7 +5645,7 @@ snapshots: dependencies: signal-exit: 4.1.0 - ws@8.20.1: {} + ws@8.21.0: {} yallist@3.1.1: {} diff --git a/web/src/routes/openid/callback.tsx b/web/src/routes/openid/callback.tsx index 466d030..67ba7cb 100644 --- a/web/src/routes/openid/callback.tsx +++ b/web/src/routes/openid/callback.tsx @@ -1,7 +1,9 @@ import { createFileRoute, redirect } from '@tanstack/react-router'; import z from 'zod'; +import { m } from '../../paraglide/messages'; import { api } from '../../shared/api/api'; import { useEnrollmentStore } from '../../shared/hooks/useEnrollmentStore'; +import { useOpenidStore } from '../../shared/hooks/useOpenIdStore'; const schema = z.object({ state: z.string().trim().min(1), @@ -26,8 +28,10 @@ export const Route = createFileRoute('/openid/callback')({ }, }) .catch((e) => { - console.error(e); - throw redirect({ to: '/enrollment-start', replace: true }); + useOpenidStore.setState({ + error: e.response?.data?.error ?? m.openid_generic_error(), + }); + throw redirect({ to: '/openid/error', replace: true }); }); const enrollmentStartResponse = await api.enrollment.start .callbackFn({