Skip to content

Commit cbe57f7

Browse files
NFC-82 Add callback
Signed-off-by: Sander Kondratjev <[email protected]>
1 parent d7588c8 commit cbe57f7

File tree

4 files changed

+103
-60
lines changed

4 files changed

+103
-60
lines changed

example/src/main/java/eu/webeid/example/web/rest/SigningController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public ResponseEntity<MobileInitRequest> mobileInit(WebEidAuthentication authent
7878

7979
@GetMapping("mobile/certificate")
8080
public ModelAndView mobileCertificateResponse() {
81-
return new ModelAndView("welcome");
81+
return new ModelAndView("mobile-callback");
8282
}
8383

8484
@SuppressWarnings("javax.annotation.Tainted")
@@ -89,7 +89,7 @@ public ResponseEntity<MobileInitRequest> mobileCertificate(@RequestBody Certific
8989

9090
@GetMapping("mobile/signature")
9191
public ModelAndView mobileSignatureResponse() {
92-
return new ModelAndView("welcome");
92+
return new ModelAndView("mobile-callback");
9393
}
9494

9595
@PostMapping("mobile/signature")

example/src/main/resources/static/css/main.css

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,25 @@ body {
116116
background-color: transparent !important;
117117
}
118118

119+
/* Mobile callback loading styles */
120+
.loading-page {
121+
text-align: center;
122+
padding-top: 3rem;
123+
font-family: system-ui, sans-serif;
124+
}
125+
126+
.spinner {
127+
width: 40px;
128+
height: 40px;
129+
border: 4px solid #ccc;
130+
border-top-color: #007bff;
131+
border-radius: 50%;
132+
animation: spin 1s linear infinite;
133+
margin: 1rem auto;
134+
}
135+
136+
@keyframes spin {
137+
to {
138+
transform: rotate(360deg);
139+
}
140+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8"/>
5+
<meta name="viewport" content="width=device-width, initial-scale=1"/>
6+
<meta http-equiv="Cache-Control" content="no-store"/>
7+
<meta id="csrftoken" name="csrftoken" th:content="${_csrf.token}"/>
8+
<meta id="csrfheadername" name="csrfheadername" th:content="${_csrf.headerName}"/>
9+
<title>Completing signing…</title>
10+
<link rel="stylesheet" href="/css/main.css"/>
11+
</head>
12+
13+
<body class="loading-page">
14+
<h2>Completing signing…</h2>
15+
<div class="spinner"></div>
16+
17+
<script>
18+
(async () => {
19+
try {
20+
const fragment = window.location.hash.slice(1);
21+
22+
if (!fragment) {
23+
throw new Error("Missing payload fragment");
24+
}
25+
26+
const decoded = atob(fragment);
27+
const payload = JSON.parse(decoded);
28+
29+
const csrfHeaderName = document.querySelector('#csrfheadername').content;
30+
const csrfToken = document.querySelector('#csrftoken').content;
31+
const path = window.location.pathname;
32+
33+
let endpoint;
34+
if (path.includes("/sign/mobile/certificate")) {
35+
endpoint = "/sign/mobile/certificate";
36+
37+
payload.certificate = payload.certificate || payload.signingCertificate || null;
38+
payload.supportedSignatureAlgorithms = payload.supportedSignatureAlgorithms || [];
39+
40+
} else if (path.includes("/sign/mobile/signature")) {
41+
endpoint = "/sign/mobile/signature";
42+
} else {
43+
throw new Error("Unexpected callback path: " + path);
44+
}
45+
46+
const response = await fetch(endpoint, {
47+
method: "POST",
48+
headers: {
49+
"Content-Type": "application/json",
50+
[csrfHeaderName]: csrfToken,
51+
},
52+
credentials: "include",
53+
body: JSON.stringify(payload),
54+
});
55+
56+
if (!response.ok) {
57+
throw new Error(await response.text());
58+
}
59+
60+
const result = await response.json();
61+
62+
if (endpoint.endsWith("/certificate")) {
63+
const { request_uri } = result;
64+
window.location.replace(request_uri);
65+
return;
66+
}
67+
68+
window.location.replace(
69+
"/welcome?signed=" + encodeURIComponent(result.name)
70+
);
71+
72+
} catch (error) {
73+
console.error("Mobile callback failed", error);
74+
window.location.replace("/welcome?error=mobile-callback");
75+
}
76+
})();
77+
</script>
78+
</body>
79+
</html>

example/src/main/resources/templates/welcome.html

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -168,64 +168,6 @@ <h2 class="adding-signature">Digital signing</h2>
168168
document.querySelector("#file-name").textContent = "Signature added: " + signedFile;
169169
}
170170
});
171-
172-
document.addEventListener("DOMContentLoaded", async () => {
173-
const path = window.location.pathname;
174-
const fragment = window.location.hash.substring(1);
175-
if (!fragment) return;
176-
177-
try {
178-
const decoded = atob(fragment);
179-
const payload = JSON.parse(decoded);
180-
181-
const csrfHeaderName = document.querySelector('#csrfheadername').content;
182-
const csrfToken = document.querySelector('#csrftoken').content;
183-
184-
if (path.includes("/sign/mobile/certificate")) {
185-
const certificate = payload.certificate || payload.signingCertificate || null;
186-
const supportedSignatureAlgorithms = payload.supportedSignatureAlgorithms || [];
187-
188-
const response = await fetch("/sign/mobile/certificate", {
189-
method: "POST",
190-
credentials: "include",
191-
headers: {
192-
"Content-Type": "application/json",
193-
[csrfHeaderName]: csrfToken,
194-
},
195-
body: JSON.stringify({ certificate, supportedSignatureAlgorithms }),
196-
});
197-
198-
if (!response.ok) throw new Error(await response.text());
199-
const { request_uri } = await response.json();
200-
window.location.href = request_uri;
201-
return;
202-
}
203-
204-
if (path.includes("/sign/mobile/signature")) {
205-
const signature = payload.signature;
206-
const signatureAlgorithm = payload.signatureAlgorithm;
207-
const signingCertificate = payload.signingCertificate || payload.certificate;
208-
209-
const response = await fetch("/sign/mobile/signature", {
210-
method: "POST",
211-
credentials: "include",
212-
headers: {
213-
"Content-Type": "application/json",
214-
[csrfHeaderName]: csrfToken,
215-
},
216-
body: JSON.stringify({ signature, signatureAlgorithm, signingCertificate }),
217-
});
218-
219-
if (!response.ok) throw new Error(await response.text());
220-
const result = await response.json();
221-
window.location.href = "/welcome?signed=" + encodeURIComponent(result.name);
222-
return;
223-
}
224-
} catch (e) {
225-
console.error("Failed to process mobile callback", e);
226-
showErrorMessage({ code: "MOBILE_CALLBACK_ERROR", message: e.message });
227-
}
228-
});
229171
</script>
230172
</body>
231173
</html>

0 commit comments

Comments
 (0)