u2f, passkey page

This commit is contained in:
peintnermax
2024-09-16 12:04:43 +02:00
parent afedbe5ab3
commit 9c6e0dcb98
5 changed files with 36 additions and 11 deletions

View File

@@ -156,12 +156,9 @@ describe("login", () => {
}, },
}); });
}); });
it("should redirect a user with passwordless authentication to /passkey/login", () => { it("should redirect a user with passwordless authentication to /passkey", () => {
cy.visit("/loginname?loginName=john%40zitadel.com&submit=true"); cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
cy.location("pathname", { timeout: 10_000 }).should( cy.location("pathname", { timeout: 10_000 }).should("eq", "/passkey");
"eq",
"/passkey/login",
);
}); });
}); });
}); });

View File

@@ -68,7 +68,7 @@ After a loginname is entered, a `listUsers` request is made using the loginName
**USER FOUND:** If only one user is found, we query `listAuthenticationMethodTypes` to identify future steps. **USER FOUND:** If only one user is found, we query `listAuthenticationMethodTypes` to identify future steps.
If no authentication methods are found, we render an error stating: _User has no available authentication methods._ (exception see below.) If no authentication methods are found, we render an error stating: _User has no available authentication methods._ (exception see below.)
Now if only one method is found, we continue with the corresponding step (/password, /passkey/login). Now if only one method is found, we continue with the corresponding step (/password, /passkey).
If multiple methods are set, we prefer passkeys over any other method, so we redirect to /passkey, second option is IDP, and third is password. If multiple methods are set, we prefer passkeys over any other method, so we redirect to /passkey, second option is IDP, and third is password.
If password is the next step, we check `loginSettings.passkeysType` for PasskeysType.ALLOWED, and prompt the user to setup passkeys afterwards. If password is the next step, we check `loginSettings.passkeysType` for PasskeysType.ALLOWED, and prompt the user to setup passkeys afterwards.
@@ -123,3 +123,33 @@ If `email` or `sms` is requested as method, the current session of the user is u
The `time-based` (TOTP) method does not require a trigger, therefore no `updateSession()` is performed and no resendLink under the code field is shown. The `time-based` (TOTP) method does not require a trigger, therefore no `updateSession()` is performed and no resendLink under the code field is shown.
The submission of the code updates the session and continues to sign in the user. The submission of the code updates the session and continues to sign in the user.
### /u2f
<img src="./screenshots/u2f.png" alt="/u2f" width="400px" />
This page requests a webAuthN challenge for the user and updates the session afterwards.
Requests to the APIs made:
- `getBrandingSettings(org?)`
- `getSession()`
- `updateSession()`
When updating the session for the webAuthN challenge, we set `userVerificationRequirement` to `UserVerificationRequirement.DISCOURAGED` as this will request the webAuthN method as second factor and not as primary method.
After updating the session, the user is signed in.
### /passkey
<img src="./screenshots/passkey.png" alt="/passkey" width="400px" />
This page requests a webAuthN challenge for the user and updates the session afterwards.
Requests to the APIs made:
- `getBrandingSettings(org?)`
- `getSession()`
- `updateSession()`
When updating the session for the webAuthN challenge, we set `userVerificationRequirement` to `UserVerificationRequirement.REQUIRED` as this will request the webAuthN method as primary method to login.
After updating the session, the user is signed in.

View File

@@ -123,9 +123,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
command.organization ?? session.factors?.user?.organizationId; command.organization ?? session.factors?.user?.organizationId;
} }
return redirect( return redirect("/passkey?" + new URLSearchParams(paramsPasskey));
"/passkey/login?" + new URLSearchParams(paramsPasskey),
);
} }
} else { } else {
// prefer passkey in favor of other methods // prefer passkey in favor of other methods
@@ -144,7 +142,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
command.organization ?? session.factors?.user?.organizationId; command.organization ?? session.factors?.user?.organizationId;
} }
return redirect("/passkey/login?" + new URLSearchParams(passkeyParams)); return redirect("/passkey?" + new URLSearchParams(passkeyParams));
} else if ( } else if (
methods.authMethodTypes.includes(AuthenticationMethodType.IDP) methods.authMethodTypes.includes(AuthenticationMethodType.IDP)
) { ) {

View File

@@ -151,7 +151,7 @@ export default function RegisterPasskey({
// params.set("altPassword", ${false}); // without setting altPassword this does not allow password // params.set("altPassword", ${false}); // without setting altPassword this does not allow password
// params.set("loginName", resp.loginName); // params.set("loginName", resp.loginName);
router.push("/passkey/login?" + params); router.push("/passkey?" + params);
} else { } else {
router.push("/accounts?" + params); router.push("/accounts?" + params);
} }