Pass the X-Client-Package explicitly for the endpoint which needs it

This commit is contained in:
Manav Rathi
2024-06-10 16:31:27 +05:30
parent f6377b98cb
commit fc826e8acb
6 changed files with 27 additions and 15 deletions

View File

@@ -44,7 +44,7 @@ class _PasskeyPageState extends State<PasskeyPage> {
"https://accounts.ente.io/passkeys/verify?"
"passkeySessionID=${widget.sessionID}"
"&redirect=enteauth://passkey"
"&client=io.ente.auth",
"&clientPackage=io.ente.auth",
mode: LaunchMode.externalApplication,
);
}

View File

@@ -44,7 +44,7 @@ class _PasskeyPageState extends State<PasskeyPage> {
"https://accounts.ente.io/passkeys/verify?"
"passkeySessionID=${widget.sessionID}"
"&redirect=ente://passkey"
"&client=io.ente.photos",
"&clientPackage=io.ente.photos",
mode: LaunchMode.externalApplication,
);
}

View File

@@ -1,6 +1,5 @@
import { setClientPackageForAuthenticatedRequests } from "@/next/http";
import log from "@/next/log";
import { clientPackageName } from "@/next/types/app";
import type { TwoFactorAuthorizationResponse } from "@/next/types/credentials";
import { ensure } from "@/utils/ensure";
import { nullToUndefined } from "@/utils/transform";
@@ -61,15 +60,10 @@ const Page = () => {
// The server needs to know the app on whose behalf we're trying to
// authenticate.
let clientPackage = nullToUndefined(searchParams.get("client"));
// Mobile apps don't pass the client header, deduce their client package
// name from the redirect URL that they provide.
const clientPackage = nullToUndefined(searchParams.get("client"));
if (!clientPackage) {
// TODO-PK: Pass from mobile app too?
clientPackage =
clientPackageName[
redirectURL.protocol == "enteauth:" ? "auth" : "photos"
];
setStatus("unrecoverableFailure");
return;
}
localStorage.setItem("clientPackage", clientPackage);
@@ -107,6 +101,7 @@ const Page = () => {
authorizationResponse = await finishPasskeyAuthentication({
passkeySessionID,
ceremonySessionID,
clientPackage,
credential,
});
} catch (e) {

View File

@@ -422,8 +422,17 @@ export const signChallenge = async (
interface FinishPasskeyAuthenticationOptions {
passkeySessionID: string;
ceremonySessionID: string;
/**
* The package name of the client on whose behalf we're authenticating with
* the user's passkey.
*
* This is used by the backend to generate an appropriately scoped auth
* token for used by (and only by) the authenticating app.
*/
clientPackage: string;
credential: Credential;
}
/**
* Finish the authentication by providing the signed assertion to the backend.
*
@@ -436,6 +445,7 @@ interface FinishPasskeyAuthenticationOptions {
export const finishPasskeyAuthentication = async ({
passkeySessionID,
ceremonySessionID,
clientPackage,
credential,
}: FinishPasskeyAuthenticationOptions) => {
const response = authenticatorAssertionResponse(credential);
@@ -452,11 +462,14 @@ export const finishPasskeyAuthentication = async ({
const params = new URLSearchParams({
sessionID: passkeySessionID,
ceremonySessionID,
clientPackage,
});
const url = `${apiOrigin()}/users/two-factor/passkeys/finish`;
const res = await fetch(`${url}?${params.toString()}`, {
method: "POST",
headers: clientPackageHeaderIfPresent(),
headers: {
"X-Client-Package": clientPackage,
},
body: JSON.stringify({
id: credential.id,
// This is meant to be the ArrayBuffer version of the (base64

View File

@@ -341,7 +341,7 @@ is needed anyways to service credential authentication from mobile clients, so
we use the same flow for other (web, desktop) clients too.
```tsx
window.location.href = `${accountsAppURL()}/passkeys/verify?passkeySessionID=${passkeySessionID}&client=io.ente.photos.web&redirect=${
window.location.href = `${accountsAppURL()}/passkeys/verify?passkeySessionID=${passkeySessionID}&clientPackage=io.ente.photos.web&redirect=${
window.location.origin
}/passkeys/finish`;
```

View File

@@ -28,9 +28,13 @@ export const redirectUserToPasskeyVerificationFlow = (
appName: AppName,
passkeySessionID: string,
) => {
const client = clientPackageName[appName];
const clientPackage = clientPackageName[appName];
const redirect = `${window.location.origin}/passkeys/finish`;
const params = new URLSearchParams({ client, passkeySessionID, redirect });
const params = new URLSearchParams({
clientPackage,
passkeySessionID,
redirect,
});
window.location.href = `${accountsAppURL()}/passkeys/verify?${params.toString()}`;
};