Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions src/lib/attestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,17 @@ const FakeAttestationDocumentSchema = z.object({

type FakeAttestationDocument = z.infer<typeof FakeAttestationDocumentSchema>;

const LOCAL_DEVELOPMENT_API_HOSTS = new Set(["127.0.0.1", "localhost", "0.0.0.0", "[::1]"]);

export function isLocalDevelopmentApiUrl(apiUrl: string): boolean {
try {
const url = new URL(apiUrl);
return url.protocol === "http:" && LOCAL_DEVELOPMENT_API_HOSTS.has(url.hostname.toLowerCase());
} catch {
return false;
}
}

async function fakeAuthenticate(
attestationDocumentBase64: string
): Promise<FakeAttestationDocument> {
Expand All @@ -269,12 +280,7 @@ export async function verifyAttestation(
const apiUrl = explicitApiUrl || getApiUrl();

// With a local backend we get a fake attestation document, so we'll just pretend to authenticate it
if (
apiUrl &&
(apiUrl === "http://127.0.0.1:3000" ||
apiUrl === "http://localhost:3000" ||
apiUrl === "http://0.0.0.0:3000")
) {
if (apiUrl && isLocalDevelopmentApiUrl(apiUrl)) {
console.log("DEV MODE: Using fake attestation document");
const fakeDocument = await fakeAuthenticate(attestationDocumentBase64);
return fakeDocument as AttestationDocument;
Expand Down
34 changes: 33 additions & 1 deletion src/lib/test/integration/attestation.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { expect, test } from "bun:test";
import { createSigStructure, parseDocumentData, parseDocumentPayload } from "../../attestation";
import {
createSigStructure,
isLocalDevelopmentApiUrl,
parseDocumentData,
parseDocumentPayload
} from "../../attestation";
import { encode } from "@stablelib/base64";

const HARDCODED_TEST_ATTESTATION_DOCUMENT =
Expand Down Expand Up @@ -27,3 +32,30 @@ test("Makes CoseSign1 bytes correctly", async () => {

expect(encode(new Uint8Array(hash))).toBe(EXPECTED_SIGNATURE_STRUCTURE_DIGEST);
});

test("Recognizes local development API URLs independent of port", () => {
const localApiUrls = [
"http://127.0.0.1:31110",
"http://localhost:31110/",
"http://0.0.0.0:31110",
"http://[::1]:31110"
];

for (const apiUrl of localApiUrls) {
expect(isLocalDevelopmentApiUrl(apiUrl)).toBe(true);
}
});

test("Does not recognize production or invalid API URLs as local development URLs", () => {
const nonLocalApiUrls = [
"https://api.opensecret.cloud",
"https://localhost:31110",
"http://api.opensecret.cloud",
"localhost:31110",
"not a url"
];

for (const apiUrl of nonLocalApiUrls) {
expect(isLocalDevelopmentApiUrl(apiUrl)).toBe(false);
}
});
Loading