Skip to content

Commit

Permalink
feat: add sanity check
Browse files Browse the repository at this point in the history
  • Loading branch information
coroiu committed Jun 7, 2024
1 parent dea8c5d commit 2961d8c
Showing 1 changed file with 38 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from "../../abstractions/fido2/fido2-client.service.abstraction";
import { Utils } from "../../misc/utils";

import * as DomainUtils from "./domain-utils";
import { Fido2AuthenticatorService } from "./fido2-authenticator.service";
import { Fido2ClientService } from "./fido2-client.service";
import { Fido2Utils } from "./fido2-utils";
Expand All @@ -36,6 +37,7 @@ describe("FidoAuthenticatorService", () => {
let domainSettingsService: MockProxy<DomainSettingsService>;
let client!: Fido2ClientService;
let tab!: chrome.tabs.Tab;
let isValidRpId!: jest.SpyInstance;

beforeEach(async () => {
authenticator = mock<Fido2AuthenticatorService>();
Expand All @@ -44,6 +46,8 @@ describe("FidoAuthenticatorService", () => {
vaultSettingsService = mock<VaultSettingsService>();
domainSettingsService = mock<DomainSettingsService>();

isValidRpId = jest.spyOn(DomainUtils, "isValidRpId");

client = new Fido2ClientService(
authenticator,
configService,
Expand All @@ -58,6 +62,10 @@ describe("FidoAuthenticatorService", () => {
tab = { id: 123, windowId: 456 } as chrome.tabs.Tab;
});

afterEach(() => {
isValidRpId.mockRestore();
});

describe("createCredential", () => {
describe("input parameters validation", () => {
// Spec: If sameOriginWithAncestors is false, return a "NotAllowedError" DOMException.
Expand Down Expand Up @@ -113,6 +121,7 @@ describe("FidoAuthenticatorService", () => {
});

// Spec: If options.rp.id is not a registrable domain suffix of and is not equal to effectiveDomain, return a DOMException whose name is "SecurityError", and terminate this algorithm.
// This is actually checked by `isValidRpId` function, but we'll test it here as well
it("should throw error if rp.id is not valid for this origin", async () => {
const params = createParams({
origin: "https://passwordless.dev",
Expand All @@ -126,6 +135,20 @@ describe("FidoAuthenticatorService", () => {
await rejects.toBeInstanceOf(DOMException);
});

// Sanity check to make sure that we use `isValidRpId` to validate the rp.id
it("should throw if isValidRpId returns false", async () => {
const params = createParams();
authenticator.makeCredential.mockResolvedValue(createAuthenticatorMakeResult());
// `params` actually has a valid rp.id, but we're mocking the function to return false
isValidRpId.mockReturnValue(false);

const result = async () => await client.createCredential(params, tab);

const rejects = expect(result).rejects;
await rejects.toMatchObject({ name: "SecurityError" });
await rejects.toBeInstanceOf(DOMException);
});

it("should fallback if origin hostname is found in neverDomains", async () => {
const params = createParams({
origin: "https://bitwarden.com",
Expand Down Expand Up @@ -370,6 +393,7 @@ describe("FidoAuthenticatorService", () => {
});

// Spec: If options.rp.id is not a registrable domain suffix of and is not equal to effectiveDomain, return a DOMException whose name is "SecurityError", and terminate this algorithm.
// This is actually checked by `isValidRpId` function, but we'll test it here as well
it("should throw error if rp.id is not valid for this origin", async () => {
const params = createParams({
origin: "https://passwordless.dev",
Expand All @@ -383,6 +407,20 @@ describe("FidoAuthenticatorService", () => {
await rejects.toBeInstanceOf(DOMException);
});

// Sanity check to make sure that we use `isValidRpId` to validate the rp.id
it("should throw if isValidRpId returns false", async () => {
const params = createParams();
authenticator.getAssertion.mockResolvedValue(createAuthenticatorAssertResult());
// `params` actually has a valid rp.id, but we're mocking the function to return false
isValidRpId.mockReturnValue(false);

const result = async () => await client.assertCredential(params, tab);

const rejects = expect(result).rejects;
await rejects.toMatchObject({ name: "SecurityError" });
await rejects.toBeInstanceOf(DOMException);
});

it("should fallback if origin hostname is found in neverDomains", async () => {
const params = createParams({
origin: "https://bitwarden.com",
Expand Down

0 comments on commit 2961d8c

Please sign in to comment.