Skip to content

Commit 9eb08a2

Browse files
committed
Catch errors in async IIFE. Use strict path comparison. Hide spinner on error.
1 parent 904d38c commit 9eb08a2

File tree

1 file changed

+67
-73
lines changed

1 file changed

+67
-73
lines changed

example/src/main/resources/templates/webeid-callback.html

Lines changed: 67 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
</head>
1313

1414
<body class="loading-page">
15-
<h2>Completing signing…</h2>
16-
<div class="spinner"></div>
17-
15+
<div id="spinner-message">
16+
<h2>Completing signing…</h2>
17+
<div class="spinner"></div>
18+
</div>
1819
<div id="error-message" class="alert alert-danger" style="display: none;" role="alert">
1920
<div class="message"></div>
2021
<pre class="details"></pre>
@@ -25,85 +26,78 @@ <h2>Completing signing…</h2>
2526
</p>
2627

2728
<script type="module">
28-
import { showErrorMessage } from '/js/errors.js';
29+
import {showErrorMessage, checkHttpError} from '/js/errors.js';
2930

31+
// Using an async IIFE for mobile WebView compatibility:
32+
// top-level await is not supported in some mobile browsers/WebViews.
3033
(async () => {
31-
try {
32-
const fragment = window.location.hash.slice(1);
33-
34-
if (!fragment) {
35-
throw new Error("Missing payload fragment");
36-
}
37-
38-
const decoded = atob(fragment);
39-
const payload = JSON.parse(decoded);
40-
41-
if (payload.error) {
42-
console.error("WebEID mobile error:", payload);
43-
44-
showErrorMessage({
45-
code: payload.code ?? "UNKNOWN_ERROR",
46-
message: payload.message ?? "Signing failed",
47-
});
48-
49-
const actions = document.getElementById("error-actions");
50-
const goBackButton = document.getElementById("back-button");
51-
actions.style.display = "block";
52-
goBackButton.addEventListener("click", () => {
53-
window.location.replace("/welcome?error=webeid-callback");
54-
});
55-
56-
return;
57-
}
58-
59-
const csrfHeaderName = document.querySelector('#csrfheadername').content;
60-
const csrfToken = document.querySelector('#csrftoken').content;
61-
const path = window.location.pathname;
34+
const fragment = window.location.hash.slice(1);
6235

63-
let endpoint;
64-
if (path.includes("/sign/mobile/certificate")) {
65-
endpoint = "/sign/mobile/certificate";
66-
67-
payload.certificate = payload.certificate || payload.signingCertificate || null;
68-
payload.supportedSignatureAlgorithms = payload.supportedSignatureAlgorithms || [];
69-
70-
} else if (path.includes("/sign/mobile/signature")) {
71-
endpoint = "/sign/mobile/signature";
72-
} else {
73-
throw new Error("Unexpected callback path: " + path);
74-
}
75-
76-
const response = await fetch(endpoint, {
77-
method: "POST",
78-
headers: {
79-
"Content-Type": "application/json",
80-
[csrfHeaderName]: csrfToken,
81-
},
82-
credentials: "include",
83-
body: JSON.stringify(payload),
84-
});
36+
if (!fragment) {
37+
throw new Error("Missing response payload");
38+
}
8539

86-
if (!response.ok) {
87-
throw new Error(await response.text());
88-
}
40+
let payload;
41+
try {
42+
payload = JSON.parse(atob(fragment));
43+
} catch (e) {
44+
console.error(e)
45+
throw new Error("Failed to parse the response");
46+
}
8947

90-
const result = await response.json();
48+
if (payload.error) {
49+
const error = new Error(payload.message ?? "Signing failed");
50+
error.code = payload.code;
51+
throw error;
52+
}
9153

92-
if (endpoint.endsWith("/certificate")) {
93-
const { request_uri } = result;
94-
window.location.replace(request_uri);
95-
return;
96-
}
54+
const path = window.location.pathname;
55+
let endpoint;
56+
if (path === "/sign/mobile/certificate") {
57+
endpoint = "/sign/mobile/certificate";
58+
} else if (path === "/sign/mobile/signature") {
59+
endpoint = "/sign/mobile/signature";
60+
} else {
61+
const error = new Error("Unexpected callback path: " + path);
62+
error.code = "INVALID_CALLBACK_PATH";
63+
throw error;
64+
}
9765

98-
window.location.replace(
99-
"/welcome?signed=" + encodeURIComponent(result.name)
100-
);
66+
const csrfHeaderName = document.querySelector('#csrfheadername').content;
67+
const csrfToken = document.querySelector('#csrftoken').content;
68+
const response = await fetch(endpoint, {
69+
method: "POST",
70+
headers: {
71+
"Content-Type": "application/json",
72+
[csrfHeaderName]: csrfToken,
73+
},
74+
credentials: "include",
75+
body: JSON.stringify(payload),
76+
});
77+
await checkHttpError(response);
78+
79+
const result = await response.json();
80+
if (endpoint.endsWith("/certificate")) {
81+
const {request_uri} = result;
82+
window.location.replace(request_uri);
83+
return;
84+
}
10185

102-
} catch (error) {
103-
console.error("Mobile callback failed", error);
86+
window.location.replace(
87+
"/welcome?signed=" + encodeURIComponent(result.name)
88+
);
89+
})().catch((error) => {
90+
console.error(error);
91+
showErrorMessage(error, "Signing failed");
92+
const spinner = document.querySelector("#spinner-message")
93+
spinner.style.display = "none";
94+
const actions = document.getElementById("error-actions");
95+
const goBackButton = document.getElementById("back-button");
96+
actions.style.display = "block";
97+
goBackButton.addEventListener("click", () => {
10498
window.location.replace("/welcome?error=webeid-callback");
105-
}
106-
})();
99+
});
100+
});
107101
</script>
108102
</body>
109103
</html>

0 commit comments

Comments
 (0)