mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-30 02:52:16 +00:00
# Which Problems Are Solved * v2 login ui was ignoring oicd `ui_locales` making it impossible to sync the login ui locale with the apps ui # How the Problems Are Solved - Read `uiLocales` from `authRequest` - check all listed if valid in ui - take the first valid one - set language cookie (if a valid locale is pressent in uiLocales) # Additional Changes - tests # Additional Context --------- Co-authored-by: Florian Forster <[email protected]> Co-authored-by: Max Peintner <[email protected]>
241 lines
7.8 KiB
TypeScript
241 lines
7.8 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { validateAuthRequest, isRSCRequest, isValidLanguage, getValidLocaleFromUILocales } from "./auth-utils";
|
|
|
|
describe("auth-utils", () => {
|
|
describe("isValidLanguage", () => {
|
|
it("should return true for valid language codes", () => {
|
|
expect(isValidLanguage("en")).toBe(true);
|
|
expect(isValidLanguage("de")).toBe(true);
|
|
expect(isValidLanguage("fr")).toBe(true);
|
|
expect(isValidLanguage("zh")).toBe(true);
|
|
});
|
|
|
|
it("should return false for invalid language codes", () => {
|
|
expect(isValidLanguage("invalid")).toBe(false);
|
|
expect(isValidLanguage("xx")).toBe(false);
|
|
expect(isValidLanguage("")).toBe(false);
|
|
});
|
|
|
|
it("should be case-insensitive", () => {
|
|
expect(isValidLanguage("EN")).toBe(true);
|
|
expect(isValidLanguage("De")).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("getValidLocaleFromUILocales", () => {
|
|
it("should return null for undefined or empty array", () => {
|
|
expect(getValidLocaleFromUILocales(undefined)).toBeNull();
|
|
expect(getValidLocaleFromUILocales([])).toBeNull();
|
|
});
|
|
|
|
it("should extract valid language from simple locale codes", () => {
|
|
expect(getValidLocaleFromUILocales(["de"])).toBe("de");
|
|
expect(getValidLocaleFromUILocales(["en", "de"])).toBe("en");
|
|
});
|
|
|
|
it("should extract language code from language tags", () => {
|
|
expect(getValidLocaleFromUILocales(["de-CH"])).toBe("de");
|
|
expect(getValidLocaleFromUILocales(["en-US"])).toBe("en");
|
|
expect(getValidLocaleFromUILocales(["zh-CN"])).toBe("zh");
|
|
});
|
|
|
|
it("should return first valid language when multiple provided", () => {
|
|
expect(getValidLocaleFromUILocales(["xx-XX", "de", "en"])).toBe("de");
|
|
});
|
|
|
|
it("should return null when no valid languages found", () => {
|
|
expect(getValidLocaleFromUILocales(["xx", "yy", "zz"])).toBeNull();
|
|
});
|
|
|
|
it("should handle case-insensitive matching", () => {
|
|
expect(getValidLocaleFromUILocales(["DE"])).toBe("de");
|
|
expect(getValidLocaleFromUILocales(["En-US"])).toBe("en");
|
|
});
|
|
});
|
|
|
|
describe("validateAuthRequest", () => {
|
|
it("should return null when no auth parameters are present", () => {
|
|
const searchParams = new URLSearchParams();
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it("should return requestId when explicitly provided", () => {
|
|
const searchParams = new URLSearchParams({
|
|
requestId: "explicit-request-123",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe("explicit-request-123");
|
|
});
|
|
|
|
it("should generate OIDC requestId from authRequest parameter", () => {
|
|
const searchParams = new URLSearchParams({
|
|
authRequest: "oidc-auth-456",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe("oidc_oidc-auth-456");
|
|
});
|
|
|
|
it("should generate SAML requestId from samlRequest parameter", () => {
|
|
const searchParams = new URLSearchParams({
|
|
samlRequest: "saml-req-789",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe("saml_saml-req-789");
|
|
});
|
|
|
|
it("should prioritize explicit requestId over authRequest", () => {
|
|
const searchParams = new URLSearchParams({
|
|
requestId: "explicit-123",
|
|
authRequest: "oidc-456",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe("explicit-123");
|
|
});
|
|
|
|
it("should prioritize explicit requestId over samlRequest", () => {
|
|
const searchParams = new URLSearchParams({
|
|
requestId: "explicit-123",
|
|
samlRequest: "saml-456",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe("explicit-123");
|
|
});
|
|
|
|
it("should handle both authRequest and samlRequest, preferring OIDC", () => {
|
|
const searchParams = new URLSearchParams({
|
|
authRequest: "oidc-123",
|
|
samlRequest: "saml-456",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe("oidc_oidc-123");
|
|
});
|
|
|
|
it("should handle empty string requestId", () => {
|
|
const searchParams = new URLSearchParams({
|
|
requestId: "",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it("should handle whitespace in requestId", () => {
|
|
const searchParams = new URLSearchParams({
|
|
requestId: " request-with-spaces ",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe(" request-with-spaces ");
|
|
});
|
|
|
|
it("should handle special characters in requestId", () => {
|
|
const searchParams = new URLSearchParams({
|
|
requestId: "request-!@#$%^&*()",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe("request-!@#$%^&*()");
|
|
});
|
|
|
|
it("should handle URL-encoded values", () => {
|
|
const searchParams = new URLSearchParams({
|
|
authRequest: "oidc encoded",
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe("oidc_oidc encoded");
|
|
});
|
|
|
|
it("should handle very long requestId values", () => {
|
|
const longId = "a".repeat(1000);
|
|
const searchParams = new URLSearchParams({
|
|
requestId: longId,
|
|
});
|
|
const result = validateAuthRequest(searchParams);
|
|
expect(result).toBe(longId);
|
|
});
|
|
});
|
|
|
|
describe("isRSCRequest", () => {
|
|
it("should return true when _rsc parameter is present", () => {
|
|
const searchParams = new URLSearchParams({
|
|
_rsc: "1",
|
|
});
|
|
const result = isRSCRequest(searchParams);
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it("should return true when _rsc parameter has empty value", () => {
|
|
const searchParams = new URLSearchParams({
|
|
_rsc: "",
|
|
});
|
|
const result = isRSCRequest(searchParams);
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it("should return false when _rsc parameter is not present", () => {
|
|
const searchParams = new URLSearchParams({
|
|
other: "param",
|
|
});
|
|
const result = isRSCRequest(searchParams);
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it("should return false for empty search params", () => {
|
|
const searchParams = new URLSearchParams();
|
|
const result = isRSCRequest(searchParams);
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it("should return true regardless of _rsc value", () => {
|
|
const searchParams = new URLSearchParams({
|
|
_rsc: "any-value-123",
|
|
});
|
|
const result = isRSCRequest(searchParams);
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it("should work with multiple parameters", () => {
|
|
const searchParams = new URLSearchParams({
|
|
authRequest: "123",
|
|
_rsc: "1",
|
|
other: "param",
|
|
});
|
|
const result = isRSCRequest(searchParams);
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it("should be case-sensitive for parameter name", () => {
|
|
const searchParams = new URLSearchParams({
|
|
_RSC: "1",
|
|
});
|
|
const result = isRSCRequest(searchParams);
|
|
expect(result).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("integration: validateAuthRequest and isRSCRequest", () => {
|
|
it("should handle typical OIDC auth flow with RSC", () => {
|
|
const searchParams = new URLSearchParams({
|
|
authRequest: "oidc-123",
|
|
_rsc: "1",
|
|
});
|
|
|
|
const requestId = validateAuthRequest(searchParams);
|
|
const isRSC = isRSCRequest(searchParams);
|
|
|
|
expect(requestId).toBe("oidc_oidc-123");
|
|
expect(isRSC).toBe(true);
|
|
});
|
|
|
|
it("should handle SAML flow without RSC", () => {
|
|
const searchParams = new URLSearchParams({
|
|
samlRequest: "saml-456",
|
|
});
|
|
|
|
const requestId = validateAuthRequest(searchParams);
|
|
const isRSC = isRSCRequest(searchParams);
|
|
|
|
expect(requestId).toBe("saml_saml-456");
|
|
expect(isRSC).toBe(false);
|
|
});
|
|
});
|
|
});
|