feat: release OTP and Passkey Tools 0.1.0
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { parseOtpAuth, serializeOtpAuth } from "../../src/otp/profile";
|
||||
|
||||
describe("otpauth profiles", () => {
|
||||
it("parses and serializes a TOTP profile without losing extensions", () => {
|
||||
const parsed = parseOtpAuth(
|
||||
"otpauth://totp/Example:alice%40example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example&algorithm=SHA256&digits=8&period=45&image=ignored",
|
||||
);
|
||||
expect(parsed.profile).toMatchObject({
|
||||
kind: "totp",
|
||||
issuer: "Example",
|
||||
account: "alice@example.com",
|
||||
algorithm: "SHA-256",
|
||||
digits: 8,
|
||||
period: 45,
|
||||
});
|
||||
expect(parsed.profile.extensions.get("image")).toBe("ignored");
|
||||
expect(serializeOtpAuth(parsed.profile)).toContain("image=ignored");
|
||||
});
|
||||
|
||||
it("requires an HOTP counter and preserves 64-bit values", () => {
|
||||
expect(() =>
|
||||
parseOtpAuth("otpauth://hotp/Example?secret=JBSWY3DPEHPK3PXP"),
|
||||
).toThrow(/counter/iu);
|
||||
const parsed = parseOtpAuth(
|
||||
"otpauth://hotp/Example?secret=JBSWY3DPEHPK3PXP&counter=18446744073709551615",
|
||||
);
|
||||
expect(parsed.profile.counter).toBe((1n << 64n) - 1n);
|
||||
});
|
||||
|
||||
it("rejects duplicate known parameters", () => {
|
||||
expect(() =>
|
||||
parseOtpAuth(
|
||||
"otpauth://totp/Example?secret=JBSWY3DPEHPK3PXP&secret=JBSWY3DPEHPK3PXP",
|
||||
),
|
||||
).toThrow(/duplicate/iu);
|
||||
});
|
||||
|
||||
it("rejects partially numeric parameters and unsafe labels", () => {
|
||||
expect(() =>
|
||||
parseOtpAuth(
|
||||
"otpauth://totp/Example?secret=JBSWY3DPEHPK3PXP&digits=6oops",
|
||||
),
|
||||
).toThrow(/integer/iu);
|
||||
const parsed = parseOtpAuth(
|
||||
"otpauth://totp/Example?secret=JBSWY3DPEHPK3PXP",
|
||||
);
|
||||
parsed.profile.account = "unsafe:label";
|
||||
expect(() => serializeOtpAuth(parsed.profile)).toThrow(/colon/iu);
|
||||
});
|
||||
|
||||
it("warns without silently reconciling issuer mismatch", () => {
|
||||
const result = parseOtpAuth(
|
||||
"otpauth://totp/Display:alice?secret=JBSWY3DPEHPK3PXP&issuer=canonical.example",
|
||||
);
|
||||
expect(result.profile.issuer).toBe("canonical.example");
|
||||
expect(result.warnings.some(({ code }) => code === "issuer-mismatch")).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user