Skip to content
File

Blob: src/worker/auth/basic.ts

typescript51 lines
1import { digestPat, parseBasicAuth, parsePat } from "@/worker/auth/pats";
2import { createControlPlaneDb } from "@/worker/db/d1/client";
3import { updatePatProjection } from "@/worker/db/d1/repository";
4import type { SubjectRow } from "@/worker/db/d1/schema";
5import type { DavScope } from "@/worker/db/types";
6import { authObject } from "@/worker/auth/session-cookie";
7 
8export interface DavPatAuth {
9 subjectId: string;
10 storageId: string;
11 hostLabel: string;
12 patId: string;
13 scopes: DavScope[];
14}
15 
16export async function authenticateDavPat(
17 env: Env,
18 request: Request,
19 subject: SubjectRow,
20 nowMs = Date.now(),
21): Promise<DavPatAuth | null> {
22 if (subject.disabledAtMs !== null) return null;
23 const credentials = parseBasicAuth(request.headers.get("authorization"));
24 if (!credentials) return null;
25 
26 const parsedPat = parsePat(credentials.password);
27 if (!parsedPat) return null;
28 
29 const digest = await digestPat(credentials.password);
30 if (!digest) return null;
31 
32 const result = await authObject(env, subject.storageId).verifyPat({
33 patId: parsedPat.id,
34 tokenDigest: digest,
35 nowMs,
36 });
37 if (!result.ok) return null;
38 
39 await updatePatProjection(createControlPlaneDb(env.DAV_CONTROL_PLANE), subject.id, parsedPat.id, {
40 lastUsedAtMs: nowMs,
41 });
42 
43 return {
44 subjectId: subject.id,
45 storageId: subject.storageId,
46 hostLabel: subject.hostLabel,
47 patId: result.pat.id,
48 scopes: result.pat.scopes,
49 };
50}