Path: blob/master/src/packages/util/auth-check-required-sso.test.ts
5837 views
import {1emailBelongsToDomain,2getEmailDomain,3checkRequiredSSO,4} from "./auth-check-required-sso";5import { Strategy } from "./types/sso";67const SSO: Readonly<Omit<Strategy, "name" | "exclusiveDomains">> = {8display: "",9backgroundColor: "",10public: false,11doNotHide: true,12updateOnLogin: true,13} as const;1415describe("Check Required SSO", () => {16test("getEmailDomain", () => {17expect(getEmailDomain("[email protected]")).toBe("bar.com");18expect(getEmailDomain("[email protected]")).toBe("bar.co.uk");19});2021test("emailBelongsToDomain", () => {22expect(emailBelongsToDomain("foo.com", "foo.com")).toBe(true);23expect(emailBelongsToDomain("bar.foo.com", "foo.com")).toBe(true);24expect(emailBelongsToDomain("foo.com", "bar.com")).toBe(false);25expect(emailBelongsToDomain("foo.com", "foo.co.uk")).toBe(false);26expect(emailBelongsToDomain("foo.com", "foo.com.uk")).toBe(false);27expect(emailBelongsToDomain("foobar.com", "bar.com")).toBe(false);28expect(emailBelongsToDomain("foobar.com", "bazfoobar.com")).toBe(false);29expect(emailBelongsToDomain("foobar.com", "*")).toBe(false);30});3132const foo = { name: "foo", exclusiveDomains: ["foo.co.uk"], ...SSO };33const bar = { name: "bar", exclusiveDomains: ["*"], ...SSO };34const baz = {35name: "baz",36exclusiveDomains: ["baz.com", "abc.com"],37...SSO,38};3940test("checkRequiredSSO", () => {41const strategies: Strategy[] = [foo, baz] as const;4243expect(checkRequiredSSO({ email: "[email protected]", strategies })?.name).toEqual(44"baz",45);46expect(47checkRequiredSSO({ email: "[email protected]", strategies })?.name,48).toEqual("baz");49expect(50checkRequiredSSO({ email: "[email protected]", strategies })?.name,51).toEqual("foo");52expect(53checkRequiredSSO({ email: "[email protected]", strategies })?.name,54).toEqual("foo");55// no match on naive substring from the right56expect(57checkRequiredSSO({ email: "[email protected]", strategies }),58).toBeUndefined();59// no catch-all for an unrelated domain, returns no strategy60expect(61checkRequiredSSO({ email: "[email protected]", strategies }),62).toBeUndefined();63});6465test("checkRequiredSSO/catchall", () => {66const strategies: Strategy[] = [foo, bar, baz] as const;6768expect(checkRequiredSSO({ email: "[email protected]", strategies })?.name).toEqual(69"baz",70);71expect(72checkRequiredSSO({ email: "[email protected]", strategies })?.name,73).toEqual("baz");74expect(75checkRequiredSSO({ email: "[email protected]", strategies })?.name,76).toEqual("foo");77// this is the essential difference to above78expect(79checkRequiredSSO({ email: "[email protected]", strategies })?.name,80).toEqual("bar");81});8283test("checkRequiredSSO/specificStrategy", () => {84const strategies: Strategy[] = [foo, bar, baz] as const;8586// When specificStrategy is set, only that strategy should match87expect(88checkRequiredSSO({89email: "[email protected]",90strategies,91specificStrategy: "baz",92})?.name,93).toEqual("baz");9495// Should not match other strategies even if domain matches96expect(97checkRequiredSSO({98email: "[email protected]",99strategies,100specificStrategy: "foo",101}),102).toBeUndefined();103104// Wildcard should work with specificStrategy105expect(106checkRequiredSSO({107email: "[email protected]",108strategies,109specificStrategy: "bar",110})?.name,111).toEqual("bar");112113// SECURITY: specificStrategy should prevent wildcard from other strategies114expect(115checkRequiredSSO({116email: "[email protected]",117strategies,118specificStrategy: "foo",119}),120).toBeUndefined();121});122123test("getEmailDomain/edge-cases", () => {124// Normal cases with whitespace and case variations125expect(getEmailDomain(" [email protected] ")).toBe("bar.com");126expect(getEmailDomain("[email protected]")).toBe("bar.com");127expect(getEmailDomain("[email protected]")).toBe("bar.com");128129// Note: Multiple @ signs (like "foo@[email protected]") are rejected by130// is_valid_email_address before getEmailDomain is called, so no test needed131});132133test("emailBelongsToDomain/normalized-domains", () => {134// Both emailDomain and ssoDomain are normalized to lowercase at the source135expect(emailBelongsToDomain("bar.com", "bar.com")).toBe(true);136expect(emailBelongsToDomain("foo.bar.com", "bar.com")).toBe(true);137138// All domains from getEmailDomain and database queries are lowercase139expect(emailBelongsToDomain("university.edu", "university.edu")).toBe(true);140expect(emailBelongsToDomain("mail.university.edu", "university.edu")).toBe(141true,142);143expect(emailBelongsToDomain("foo.com", "foo.com")).toBe(true);144145// Edge case: ensure no partial string matches146expect(emailBelongsToDomain("barbarbar.com", "bar.com")).toBe(false);147expect(emailBelongsToDomain("xbar.com", "bar.com")).toBe(false);148});149150test("checkRequiredSSO/invalid-inputs", () => {151const strategies: Strategy[] = [foo, bar, baz] as const;152153// Invalid email addresses should return undefined154expect(checkRequiredSSO({ email: "", strategies })).toBeUndefined();155expect(checkRequiredSSO({ email: undefined, strategies })).toBeUndefined();156expect(157checkRequiredSSO({ email: "notanemail", strategies }),158).toBeUndefined();159expect(160checkRequiredSSO({ email: "@domain.com", strategies }),161).toBeUndefined();162expect(checkRequiredSSO({ email: "user@", strategies })).toBeUndefined();163164// No strategies165expect(166checkRequiredSSO({ email: "[email protected]", strategies: [] }),167).toBeUndefined();168expect(169checkRequiredSSO({ email: "[email protected]", strategies: undefined }),170).toBeUndefined();171});172173test("checkRequiredSSO/strategy-priority", () => {174// When multiple strategies could match, first one wins175const dup1 = { name: "dup1", exclusiveDomains: ["test.com"], ...SSO };176const dup2 = { name: "dup2", exclusiveDomains: ["test.com"], ...SSO };177const strategies: Strategy[] = [dup1, dup2] as const;178179expect(checkRequiredSSO({ email: "[email protected]", strategies })?.name).toEqual(180"dup1",181);182183// Wildcard order matters too184const wild1 = { name: "wild1", exclusiveDomains: ["*"], ...SSO };185const wild2 = { name: "wild2", exclusiveDomains: ["*"], ...SSO };186const wildStrategies: Strategy[] = [wild1, wild2] as const;187188expect(189checkRequiredSSO({ email: "[email protected]", strategies: wildStrategies })190?.name,191).toEqual("wild1");192});193194test("checkRequiredSSO/empty-exclusiveDomains", () => {195const emptyDomains = {196name: "empty",197exclusiveDomains: [],198...SSO,199};200const strategies: Strategy[] = [emptyDomains] as const;201202expect(203checkRequiredSSO({ email: "[email protected]", strategies }),204).toBeUndefined();205});206207test("checkRequiredSSO/subdomain-matching", () => {208const strategies: Strategy[] = [baz] as const;209210// Direct domain match211expect(checkRequiredSSO({ email: "[email protected]", strategies })?.name).toEqual(212"baz",213);214215// Subdomain matches216expect(217checkRequiredSSO({ email: "[email protected]", strategies })?.name,218).toEqual("baz");219expect(220checkRequiredSSO({ email: "[email protected]", strategies })?.name,221).toEqual("baz");222223// Should not match partial string (already tested but important)224expect(225checkRequiredSSO({ email: "[email protected]", strategies }),226).toBeUndefined();227expect(228checkRequiredSSO({ email: "[email protected]", strategies }),229).toBeUndefined();230});231});232233234