Skip to content

Commit 203f171

Browse files
authored
Fix userHandle determination (#106)
1 parent 2fa468d commit 203f171

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

cdk/custom-auth/common.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ export const logLevel =
6969
export let logger = new Logger(logLevel);
7070

7171
/**
72-
* Returns the cognitoUsername if it is opaque, i.e. if it looks like a UUID, or otherwise the sub
72+
* Returns a suitable userHandle given the username and the sub
73+
* If possible we'll use the username (so that usernameless sign-in can be supported),
74+
* but this requires the username to be opaque.
7375
*/
7476
export function determineUserHandle({
7577
sub,
@@ -78,10 +80,15 @@ export function determineUserHandle({
7880
sub?: string; // maybe undefined if userNotFound is true
7981
cognitoUsername: string;
8082
}) {
83+
if (sub === cognitoUsername) return sub; // usernameless sign-in supported
8184
if (!sub || isOpaqueIdentifier(cognitoUsername)) {
82-
return cognitoUsername;
85+
/**
86+
* prefix username with "u|" so it will never (accidentally, or maliciously) collide with the sub of another user
87+
* (the Cognito sub is a hexadecimally represented UUID that will not start with "u|")
88+
*/
89+
return `u|${cognitoUsername}`; // usernameless sign-in supported
8390
}
84-
return sub;
91+
return `s|${sub}`; // usernameless sign-in NOT supported, we prefix with "s|" so the UI can detect this
8592
}
8693

8794
function isOpaqueIdentifier(cognitoUsername: string) {

client/fido2.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,15 @@ export function authenticateWithFido2({
547547
username = new TextDecoder().decode(
548548
bufferFromBase64Url(fido2credential.userHandleB64)
549549
);
550+
// The userHandle must map to a username, not a sub
551+
if (username.startsWith("s|")) {
552+
debug?.(
553+
"Credential userHandle isn't a username. In order to use the username as userHandle, so users can sign in without typing their username, usernames must be opaque"
554+
);
555+
throw new Error("Username is required for initiating sign-in");
556+
}
557+
// remove (potential) prefix to recover username
558+
username = username.replace(/^u\|/, "");
550559
debug?.(
551560
`Proceeding with discovered credential for username: ${username} (b64: ${fido2credential.userHandleB64})`
552561
);

0 commit comments

Comments
 (0)