google-labs-jules[bot] 589e146ecc feat(routes): decompose admin and auth monolith routes
Extracted domain-specific sub-routers from monolithic `server/routes/admin.ts` and `server/routes/auth.ts` into isolated modules within `server/routes/admin/` and `server/routes/auth/` respectively. The original entry routers were updated to import and assemble these sub-routers without breaking their current HTTP interface or rate limiting/authorization middleware. Testing and linting were run ensuring perfect functionality and 100% test passing score.

Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
2026-08-26 04:37:26 +00:00

269 lines
7.9 KiB
TypeScript

import { Hono } from "jsr:@hono/hono@4";
import { getCookie, setCookie } from "jsr:@hono/hono@4/cookie";
import { encodeBase64Url } from "jsr:@std/encoding@1/base64url";
import {
generateRegistrationOptions,
MetadataService,
verifyRegistrationResponse,
} from "jsr:@simplewebauthn/server@13";
import type { RegistrationResponseJSON } from "jsr:@simplewebauthn/server@13";
import { sqlWrapper } from "../../db.ts";
import { auditWrapper } from "../../audit.ts";
import {
getAuthenticatedUser,
requirePrimarySession,
} from "../../auth-session.ts";
import { getClientIp } from "../../middleware.ts";
export const passkeysAuthRoutes = new Hono();
const rpName = "Auth-Yes Identity Provider";
const rpID = Deno.env.get("RP_ID") ||
(import.meta.main ? undefined : "localhost");
const origin = Deno.env.get("ORIGIN") ||
(import.meta.main ? undefined : "http://localhost");
const requireHardwareToken = Deno.env.get("REQUIRE_HARDWARE_TOKEN") === "true";
passkeysAuthRoutes.use("/api/passkeys/*", requirePrimarySession);
// ---------------------------------------------------------
// Authenticated Passkey Registration (Adding a new device)
// ---------------------------------------------------------
passkeysAuthRoutes.post("/api/passkeys/register/challenge", async (c) => {
const auth = await getAuthenticatedUser(c);
if (!auth) return c.json({ error: "Unauthorized" }, 401);
const user = await sqlWrapper
.sql`SELECT username FROM users WHERE id = ${auth.userId}`
.then((res: any) => res[0]);
if (!user) return c.json({ error: "User not found" }, 404);
const userIdBytes = new TextEncoder().encode(auth.userId);
if (!rpID) throw new Error("rpID is missing");
const options = await generateRegistrationOptions({
rpName,
rpID,
userName: user.username,
userID: userIdBytes,
attestationType: "direct",
authenticatorSelection: {
residentKey: "required",
requireResidentKey: true,
userVerification: "preferred",
},
timeout: 60000,
});
setCookie(c, "expected_add_passkey_challenge", options.challenge, {
httpOnly: true,
secure: true,
sameSite: "Lax",
maxAge: 300,
});
return c.json({ options });
});
passkeysAuthRoutes.post("/api/passkeys/register/verify", async (c) => {
const auth = await getAuthenticatedUser(c);
if (!auth) return c.json({ error: "Unauthorized" }, 401);
const { response } = await c.req.json();
const expectedChallenge = getCookie(c, "expected_add_passkey_challenge");
if (!expectedChallenge) {
return c.json({ error: "Missing or expired registration challenge" }, 400);
}
if (!origin || !rpID) throw new Error("Missing origin or rpID");
let verification;
try {
verification = await verifyRegistrationResponse({
response: response as RegistrationResponseJSON,
expectedChallenge,
expectedOrigin: origin,
expectedRPID: rpID,
requireUserVerification: false,
});
} catch (error: any) {
return c.json({ error: error.message }, 400);
}
const { verified, registrationInfo } = verification;
if (!verified || !registrationInfo) {
return c.json({ error: "Verification failed" }, 400);
}
// Enterprise Allow-List Verification
const allowlistCount = await sqlWrapper
.sql`SELECT COUNT(*) as count FROM aaguid_allowlist`.then((res: any) =>
Number(res[0].count)
);
if (allowlistCount > 0 && registrationInfo.aaguid) {
const isAllowed = await sqlWrapper
.sql`SELECT id FROM aaguid_allowlist WHERE aaguid = ${registrationInfo.aaguid}`
.then((res: any) => res[0]);
if (!isAllowed) {
auditWrapper.auditLog(auth.userId, "failed_attestation_allowlist", null, {
aaguid: registrationInfo.aaguid,
}, getClientIp(c));
return c.json({
error: "Authenticator AAGUID is not in the enterprise allow-list.",
}, 403);
}
}
// Optional Strict Hardware Attestation
if (requireHardwareToken) {
if (
!registrationInfo.aaguid ||
registrationInfo.aaguid === "00000000-0000-0000-0000-000000000000"
) {
auditWrapper.auditLog(
auth.userId,
"add_passkey_failed_attestation",
null,
{
reason: "No AAGUID provided",
},
getClientIp(c),
);
return c.json(
{ error: "Hardware attestation failed: No AAGUID provided." },
403,
);
}
let mdsStatement;
try {
mdsStatement = await MetadataService.getStatement(
registrationInfo.aaguid,
);
} catch (mdsError) {
console.warn("[Auth API] MetadataService lookup error:", mdsError);
}
if (!mdsStatement) {
auditWrapper.auditLog(
auth.userId,
"add_passkey_failed_attestation",
null,
{
aaguid: registrationInfo.aaguid,
reason: "AAGUID not found in MDS3",
},
getClientIp(c),
);
return c.json({
error:
`Hardware attestation failed: Authenticator AAGUID (${registrationInfo.aaguid}) not found in FIDO MDS3 blob.`,
}, 403);
}
// @ts-ignore: FIDO MDS3 missing type
if (mdsStatement.keyProtection?.includes(0x0001)) {
auditWrapper.auditLog(
auth.userId,
"add_passkey_failed_attestation",
null,
{
aaguid: registrationInfo.aaguid,
reason: "Software passkey detected",
},
getClientIp(c),
);
return c.json({
error:
"Hardware attestation failed: Authenticator is flagged as a software-based passkey.",
}, 403);
}
}
const credentialID = registrationInfo.credential.id;
const credentialPublicKey = registrationInfo.credential.publicKey;
const counter = registrationInfo.credential.counter;
const base64CredentialID = typeof credentialID === "string"
? credentialID
: encodeBase64Url(new Uint8Array(credentialID as unknown as ArrayBuffer));
const base64PublicKey = encodeBase64Url(
new Uint8Array(credentialPublicKey as unknown as ArrayBuffer),
);
await sqlWrapper.sql`
INSERT INTO passkeys (user_id, credential_id, public_key, counter)
VALUES (${auth.userId}, ${base64CredentialID}, ${base64PublicKey}, ${counter})
`;
auditWrapper.auditLog(
auth.userId,
"passkey_added",
null,
null,
getClientIp(c),
);
setCookie(c, "expected_add_passkey_challenge", "", {
httpOnly: true,
secure: true,
sameSite: "Lax",
maxAge: 0,
});
return c.json({ success: true });
});
// Get user's registered passkeys
passkeysAuthRoutes.get("/api/passkeys", async (c) => {
const auth = await getAuthenticatedUser(c);
if (!auth) return c.json({ error: "Unauthorized" }, 401);
const passkeys = await sqlWrapper.sql`
SELECT id, counter
FROM passkeys
WHERE user_id = ${auth.userId}
`;
return c.json({ passkeys });
});
// Revoke a specific passkey
passkeysAuthRoutes.delete("/api/passkeys/:id", async (c) => {
const auth = await getAuthenticatedUser(c);
if (!auth) return c.json({ error: "Unauthorized" }, 401);
const targetPasskeyId = c.req.param("id");
// Verify the passkey belongs to the user
const passkey = await sqlWrapper.sql`
SELECT id FROM passkeys WHERE id = ${targetPasskeyId} AND user_id = ${auth.userId}
`.then((res: any) => res[0]);
if (!passkey) {
return c.json({ error: "Passkey not found or access denied" }, 404);
}
// Prevent deleting the very last passkey to avoid locking out the user
const passkeyCount = await sqlWrapper.sql`
SELECT count(*) as count FROM passkeys WHERE user_id = ${auth.userId}
`.then((res: any) => Number(res[0].count));
if (passkeyCount <= 1) {
return c.json({
error: "Cannot delete your last passkey. Register another one first.",
}, 400);
}
await sqlWrapper.sql`DELETE FROM passkeys WHERE id = ${targetPasskeyId}`;
auditWrapper.auditLog(auth.userId, "passkey_revoked", null, {
revoked_passkey_id: targetPasskeyId,
}, getClientIp(c));
return c.json({ success: true });
});