Skip to content

Commit fc5bca6

Browse files
committed
feat: error messages on W3ID mismatch
1 parent fd242ff commit fc5bca6

File tree

5 files changed

+95
-19
lines changed

5 files changed

+95
-19
lines changed

platforms/eVoting/src/components/signing-interface.tsx

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function SigningInterface({ pollId, voteData, onSigningComplete, onCancel
2222
const { SVG } = useQRCode();
2323
const [sessionId, setSessionId] = useState<string | null>(null);
2424
const [qrData, setQrData] = useState<string | null>(null);
25-
const [status, setStatus] = useState<"pending" | "connecting" | "signed" | "expired" | "error">("pending");
25+
const [status, setStatus] = useState<"pending" | "connecting" | "signed" | "expired" | "error" | "security_violation">("pending");
2626
const [timeRemaining, setTimeRemaining] = useState<number>(900); // 15 minutes in seconds
2727
const [eventSource, setEventSource] = useState<EventSource | null>(null);
2828
const { toast } = useToast();
@@ -100,6 +100,13 @@ export function SigningInterface({ pollId, voteData, onSigningComplete, onCancel
100100
description: "The signing session has expired. Please try again.",
101101
variant: "destructive",
102102
});
103+
} else if (data.type === "security_violation") {
104+
setStatus("security_violation");
105+
toast({
106+
title: "Security Violation",
107+
description: data.error || "Public key verification failed",
108+
variant: "destructive",
109+
});
103110
} else {
104111
}
105112
} catch (error) {
@@ -135,16 +142,16 @@ export function SigningInterface({ pollId, voteData, onSigningComplete, onCancel
135142
// Cleanup SSE connection
136143
useEffect(() => {
137144
return () => {
138-
// Only close SSE connection if signing is not complete
139-
if (eventSource && status !== "signed") {
145+
// Only close SSE connection if signing is not complete or if there's a security violation
146+
if (eventSource && status !== "signed" && status !== "security_violation") {
140147
eventSource.close();
141148
}
142149
};
143150
}, [eventSource, status]);
144151

145-
// Additional cleanup when signing is complete
152+
// Additional cleanup when signing is complete or security violation occurs
146153
useEffect(() => {
147-
if (status === "signed" && eventSource) {
154+
if ((status === "signed" || status === "security_violation") && eventSource) {
148155
eventSource.close();
149156
}
150157
}, [status, eventSource]);
@@ -222,6 +229,33 @@ export function SigningInterface({ pollId, voteData, onSigningComplete, onCancel
222229
);
223230
}
224231

232+
if (status === "security_violation") {
233+
return (
234+
<Card className="w-full max-w-md mx-auto">
235+
<CardHeader className="text-center">
236+
<CardTitle className="flex items-center justify-center gap-2">
237+
<AlertTriangle className="h-5 w-5 text-red-500" />
238+
Security Violation
239+
</CardTitle>
240+
<CardDescription>
241+
eName verification failed
242+
</CardDescription>
243+
</CardHeader>
244+
<CardContent className="text-center space-y-4">
245+
<div className="bg-red-50 p-4 rounded-lg">
246+
<p className="text-red-800 text-sm">
247+
eName Mismatch: It appears that you are trying to sign with the wrong eName.
248+
Please make sure you are signing with the right eID linked to this account.
249+
</p>
250+
</div>
251+
<Button onClick={onCancel} variant="secondary">
252+
Close
253+
</Button>
254+
</CardContent>
255+
</Card>
256+
);
257+
}
258+
225259
if (status === "signed") {
226260
return (
227261
<Card className="w-full max-w-md mx-auto">

platforms/evoting-api/src/controllers/SigningController.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,12 @@ export class SigningController {
123123
voteId: result.voteId
124124
});
125125
} else {
126-
res.status(400).json({
126+
// Always send 200 response to the wallet, even for security violations
127+
// This prevents the wallet from thinking the request failed
128+
res.status(200).json({
127129
success: false,
128-
error: result.error
130+
error: result.error,
131+
message: "Request processed but vote not submitted due to verification failure"
129132
});
130133
}
131134
} catch (error) {

platforms/evoting-api/src/services/SigningService.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface SigningSession {
88
userId: string;
99
voteData: any;
1010
qrData: string;
11-
status: "pending" | "signed" | "expired" | "completed";
11+
status: "pending" | "signed" | "expired" | "completed" | "security_violation";
1212
expiresAt: Date;
1313
createdAt: Date;
1414
updatedAt: Date;
@@ -150,6 +150,21 @@ export class SigningService {
150150
cleanUserEname,
151151
sessionUserId: session.userId
152152
});
153+
154+
// Update session status to indicate security violation
155+
session.status = "security_violation";
156+
session.updatedAt = new Date();
157+
this.sessions.set(sessionId, session);
158+
159+
// Notify subscribers of security violation
160+
this.notifySubscribers(sessionId, {
161+
type: "security_violation",
162+
status: "security_violation",
163+
error: "Public key does not match the user who created this signing session",
164+
sessionId
165+
});
166+
167+
// Return success: false but don't throw error - let the wallet think it succeeded
153168
return { success: false, error: "Public key does not match the user who created this signing session" };
154169
}
155170

platforms/group-charter-manager-api/src/controllers/CharterSigningController.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,21 @@ export class CharterSigningController {
140140
message
141141
);
142142

143-
res.json({
144-
success: true,
145-
message: "Signature verified and charter signed",
146-
data: result
147-
});
143+
if (result.success) {
144+
res.json({
145+
success: true,
146+
message: "Signature verified and charter signed",
147+
data: result
148+
});
149+
} else {
150+
// Always send 200 response to the wallet, even for security violations
151+
// This prevents the wallet from thinking the request failed
152+
res.status(200).json({
153+
success: false,
154+
error: result.error,
155+
message: "Request processed but charter not signed due to verification failure"
156+
});
157+
}
148158

149159
} catch (error) {
150160
console.error("Error processing signed payload:", error);

platforms/group-charter-manager-api/src/services/CharterSigningService.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export interface CharterSigningSession {
99
qrData: string;
1010
createdAt: Date;
1111
expiresAt: Date;
12-
status: "pending" | "signed" | "expired" | "completed";
12+
status: "pending" | "signed" | "expired" | "completed" | "security_violation";
1313
}
1414

1515
export interface SignedCharterPayload {
@@ -21,13 +21,14 @@ export interface SignedCharterPayload {
2121

2222
export interface CharterSigningResult {
2323
success: boolean;
24+
error?: string;
2425
sessionId: string;
2526
groupId: string;
2627
userId: string;
27-
signature: string;
28-
publicKey: string;
29-
message: string;
30-
type: "signed";
28+
signature?: string;
29+
publicKey?: string;
30+
message?: string;
31+
type: "signed" | "security_violation";
3132
}
3233

3334
export class CharterSigningService {
@@ -136,7 +137,20 @@ export class CharterSigningService {
136137
cleanUserEname,
137138
sessionUserId: session.userId
138139
});
139-
throw new Error("Public key does not match the user who created this signing session");
140+
141+
// Update session status to indicate security violation
142+
session.status = "security_violation";
143+
this.sessions.set(sessionId, session);
144+
145+
// Return error result instead of throwing
146+
return {
147+
success: false,
148+
error: "Public key does not match the user who created this signing session",
149+
sessionId,
150+
groupId: session.groupId,
151+
userId: session.userId,
152+
type: "security_violation"
153+
};
140154
}
141155

142156
console.log(`✅ Public key verification passed: ${cleanPublicKey} matches ${cleanUserEname}`);

0 commit comments

Comments
 (0)