Merge commit from fork

* fix: Improve host header handling and deployment mode detection

* ZITADEL_CLOUD env

* refactor service config

* service config

* cleanup

* cleanup

* util for original and public host

* instanceHost, publicHost

* cleanup constructUrl

* cleanup middleware

* add x-zitadel-forward-host as fallback for current cloud setup

* fix build

* fix: lint

* fix: update test mocks

* fix: provide basepath to unit tests

* host handling

* unit tests

* imports

* fix: getPublicHost instead of getInstanceHost

* unit tests

* update nextjs, implement jwt verify for logout_token

* pass logout information in jwt to login v2

* handle hosts in jwks url

* point idp callbacks to the api and not the login UI

* logout_hint out of logout token, typecheck

* rm unused imports

* fix oidc integration test

---------

Co-authored-by: Livio Spring <[email protected]>
This commit is contained in:
Max Peintner
2025-12-08 10:01:49 +01:00
committed by GitHub
co-authored by Livio Spring
parent f9e3871bb3
commit df75be96ff
75 changed files with 2075 additions and 1817 deletions
+36 -36
View File
@@ -101,7 +101,7 @@ describe("isSessionValid", () => {
factors: undefined,
});
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(false);
expect(consoleSpy).toHaveBeenCalledWith("Session has no user");
@@ -120,7 +120,7 @@ describe("isSessionValid", () => {
authMethodTypes: [],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(false);
expect(consoleSpy).toHaveBeenCalledWith("Session is expired", expect.any(String));
@@ -147,7 +147,7 @@ describe("isSessionValid", () => {
authMethodTypes: [],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(false);
});
@@ -179,7 +179,7 @@ describe("isSessionValid", () => {
forceMfaLocalOnly: false,
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -207,7 +207,7 @@ describe("isSessionValid", () => {
forceMfaLocalOnly: false,
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -242,7 +242,7 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(true);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(false);
expect(consoleSpy).toHaveBeenCalledWith(
@@ -278,7 +278,7 @@ describe("isSessionValid", () => {
authMethodTypes: [AuthenticationMethodType.OTP_EMAIL],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -307,7 +307,7 @@ describe("isSessionValid", () => {
authMethodTypes: [AuthenticationMethodType.U2F],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -342,7 +342,7 @@ describe("isSessionValid", () => {
authMethodTypes: [AuthenticationMethodType.TOTP, AuthenticationMethodType.OTP_EMAIL],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -372,7 +372,7 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(false);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -409,7 +409,7 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(false);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -447,7 +447,7 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(true);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(false);
expect(consoleSpy).toHaveBeenCalledWith(
@@ -499,7 +499,7 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(false);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
// This should be true - if it's false, the original bug still exists
expect(result).toBe(true);
@@ -539,7 +539,7 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(false);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
// With our fix, this should be true (session is valid)
// With the old logic, this would have been false (bug)
@@ -576,7 +576,7 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(false);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -611,7 +611,7 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(true);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(false);
expect(consoleSpy).toHaveBeenCalledWith("Session has no valid multifactor", expect.any(Object));
@@ -647,7 +647,7 @@ describe("isSessionValid", () => {
forceMfaLocalOnly: false,
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -681,7 +681,7 @@ describe("isSessionValid", () => {
forceMfaLocalOnly: true,
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -716,15 +716,15 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(true);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(false);
expect(zitadelModule.getLoginSettings).toHaveBeenCalledWith({
serviceUrl: mockServiceUrl,
serviceConfig: { baseUrl: mockServiceUrl },
organization: mockOrganizationId,
});
expect(zitadelModule.listAuthenticationMethodTypes).toHaveBeenCalledWith({
serviceUrl: mockServiceUrl,
serviceConfig: { baseUrl: mockServiceUrl },
userId: mockUserId,
});
consoleSpy.mockRestore();
@@ -777,7 +777,7 @@ describe("isSessionValid", () => {
},
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(false);
expect(consoleSpy).toHaveBeenCalledWith(
@@ -831,7 +831,7 @@ describe("isSessionValid", () => {
},
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -866,7 +866,7 @@ describe("isSessionValid", () => {
vi.mocked(verifyHelperModule.shouldEnforceMFA).mockReturnValue(false);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
// getUserByID should not be called when EMAIL_VERIFICATION is disabled
@@ -902,7 +902,7 @@ describe("isSessionValid", () => {
forceMfaLocalOnly: false,
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -938,12 +938,12 @@ describe("isSessionValid", () => {
authMethodTypes: [],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
expect(verifyHelperModule.shouldEnforceMFA).toHaveBeenCalledWith(session, expect.any(Object));
expect(zitadelModule.getLoginSettings).toHaveBeenCalledWith({
serviceUrl: mockServiceUrl,
serviceConfig: { baseUrl: mockServiceUrl },
organization: mockOrganizationId,
});
});
@@ -979,16 +979,16 @@ describe("isSessionValid", () => {
authMethodTypes: [AuthenticationMethodType.TOTP, AuthenticationMethodType.OTP_EMAIL],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(false);
expect(verifyHelperModule.shouldEnforceMFA).toHaveBeenCalledWith(session, expect.any(Object));
expect(zitadelModule.getLoginSettings).toHaveBeenCalledWith({
serviceUrl: mockServiceUrl,
serviceConfig: { baseUrl: mockServiceUrl },
organization: mockOrganizationId,
});
expect(zitadelModule.listAuthenticationMethodTypes).toHaveBeenCalledWith({
serviceUrl: mockServiceUrl,
serviceConfig: { baseUrl: mockServiceUrl },
userId: mockUserId,
});
});
@@ -1024,12 +1024,12 @@ describe("isSessionValid", () => {
authMethodTypes: [AuthenticationMethodType.TOTP, AuthenticationMethodType.OTP_EMAIL],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
expect(verifyHelperModule.shouldEnforceMFA).toHaveBeenCalledWith(session, expect.any(Object));
expect(zitadelModule.getLoginSettings).toHaveBeenCalledWith({
serviceUrl: mockServiceUrl,
serviceConfig: { baseUrl: mockServiceUrl },
organization: mockOrganizationId,
});
// Should not call listAuthenticationMethodTypes since shouldEnforceMFA returned false
@@ -1067,7 +1067,7 @@ describe("isSessionValid", () => {
authMethodTypes: [AuthenticationMethodType.TOTP],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});
@@ -1105,12 +1105,12 @@ describe("isSessionValid", () => {
authMethodTypes: [AuthenticationMethodType.TOTP],
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
expect(verifyHelperModule.shouldEnforceMFA).toHaveBeenCalledWith(session, expect.any(Object));
expect(zitadelModule.getLoginSettings).toHaveBeenCalledWith({
serviceUrl: mockServiceUrl,
serviceConfig: { baseUrl: mockServiceUrl },
organization: mockOrganizationId,
});
// Should not call listAuthenticationMethodTypes since shouldEnforceMFA returned false
@@ -1146,7 +1146,7 @@ describe("isSessionValid", () => {
forceMfaLocalOnly: false,
} as any);
const result = await isSessionValid({ serviceUrl: mockServiceUrl, session });
const result = await isSessionValid({ serviceConfig: { baseUrl: mockServiceUrl }, session });
expect(result).toBe(true);
});