diff --git a/docker/Dockerfile.ui b/docker/Dockerfile.ui
index b0f3aa1a41..b865ade6f1 100644
--- a/docker/Dockerfile.ui
+++ b/docker/Dockerfile.ui
@@ -24,7 +24,7 @@ ENV NEXT_TELEMETRY_DISABLED 1
 
 # If using npm comment out above and use below instead
 ENV API_URL http://localhost:8080
-RUN npm run build
+RUN NODE_OPTIONS=--max-old-space-size=8192  npm run build
 
 
 # Production image, copy all the files and run next
diff --git a/ee/identitymanager/identity_managers/auth0/auth0_authverifier.py b/ee/identitymanager/identity_managers/auth0/auth0_authverifier.py
index ea5a5987a9..e351f5a622 100644
--- a/ee/identitymanager/identity_managers/auth0/auth0_authverifier.py
+++ b/ee/identitymanager/identity_managers/auth0/auth0_authverifier.py
@@ -42,6 +42,14 @@ def _verify_bearer_token(self, token) -> AuthenticatedEntity:
         with tracer.start_as_current_span("verify_bearer_token"):
             if not token:
                 raise HTTPException(status_code=401, detail="No token provided 👈")
+
+            # more than one tenant support
+            if token.startswith("keepActiveTenant"):
+                active_tenant, token = token.split("&")
+                active_tenant = active_tenant.split("=")[1]
+            else:
+                active_tenant = None
+
             try:
                 jwt_signing_key = jwks_client.get_signing_key_from_jwt(token).key
                 payload = jwt.decode(
@@ -52,7 +60,24 @@ def _verify_bearer_token(self, token) -> AuthenticatedEntity:
                     issuer=self.issuer,
                     leeway=60,
                 )
-                tenant_id = payload.get("keep_tenant_id")
+                # if active_tenant is set, we must verify its in the token
+                if active_tenant:
+                    active_tenant_found = False
+                    for tenant in payload.get("keep_tenant_ids", []):
+                        if tenant.get("tenant_id") == active_tenant:
+                            active_tenant_found = True
+                            break
+                    if not active_tenant_found:
+                        self.logger.warning(
+                            "Someone tries to use a token with a tenant that is not in the token"
+                        )
+                        raise HTTPException(
+                            status_code=401,
+                            detail="Token does not contain the active tenant",
+                        )
+                    tenant_id = active_tenant
+                else:
+                    tenant_id = payload.get("keep_tenant_id")
                 role_name = payload.get(
                     "keep_role", AdminRole.get_name()
                 )  # default to admin for backwards compatibility
diff --git a/keep-ui/auth.config.ts b/keep-ui/auth.config.ts
index 71ed67fa60..33fa07f546 100644
--- a/keep-ui/auth.config.ts
+++ b/keep-ui/auth.config.ts
@@ -172,6 +172,16 @@ const baseProviderConfigs = {
             tenant_id: tenantId,
             user_id: "keep-user-for-no-auth-purposes",
           }),
+          tenantIds: [
+            {
+              tenant_id: "keep",
+              tenant_name: "Tenant of Keep (tenant_id: keep)",
+            },
+            {
+              tenant_id: "keep2",
+              tenant_name: "Tenant of another Keep (tenant_id: keep2)",
+            },
+          ],
           tenantId: tenantId,
           role: "user",
         };
@@ -240,6 +250,14 @@ export const config = {
         let tenantId: string | undefined = user.tenantId;
         let role: string | undefined = user.role;
 
+        // if the account is from tenant-switch provider, return the token
+        if (account.provider === "tenant-switch") {
+          token.accessToken = user.accessToken;
+          token.tenantId = user.tenantId;
+          token.role = user.role;
+          return token;
+        }
+
         if (authType === AuthType.AZUREAD) {
           accessToken = account.access_token;
           if (account.id_token) {
@@ -261,6 +279,10 @@ export const config = {
           if ((profile as any)?.keep_role) {
             role = (profile as any).keep_role;
           }
+          // more than one tenants
+          if ((profile as any)?.keep_tenant_ids) {
+            user.tenantIds = (profile as any).keep_tenant_ids;
+          }
         } else if (authType === AuthType.KEYCLOAK) {
           // TODO: remove this once we have a proper way to get the tenant id
           tenantId = (profile as any).keep_tenant_id || "keep";
diff --git a/keep-ui/auth.ts b/keep-ui/auth.ts
index c0d49ee466..cb0ad2006e 100644
--- a/keep-ui/auth.ts
+++ b/keep-ui/auth.ts
@@ -4,6 +4,77 @@ import { config, authType, proxyUrl } from "@/auth.config";
 import { ProxyAgent, fetch as undici } from "undici";
 import MicrosoftEntraID from "next-auth/providers/microsoft-entra-id";
 import { AuthType } from "@/utils/authenticationType";
+import Credentials from "next-auth/providers/credentials";
+import { User } from "next-auth";
+
+// Implement the tenant switch provider directly in auth.ts
+const tenantSwitchProvider = Credentials({
+  id: "tenant-switch",
+  name: "Tenant Switch",
+  credentials: {
+    tenantId: { label: "Tenant ID", type: "text" },
+    sessionAsJson: { label: "Session", type: "text" },
+  },
+  async authorize(credentials, req): Promise<User | null> {
+    if (!credentials?.tenantId) {
+      throw new Error("No tenant ID provided");
+    }
+
+    let session = JSON.parse(credentials.sessionAsJson as string);
+
+    // Fallback to getting the user from cookies if session is not available
+    let user: any;
+    if (session?.user) {
+      user = session.user;
+    } else {
+      // Try to get us  er info from JWT token
+      const token = (req as any)?.token;
+      if (token) {
+        user = {
+          id: token.sub,
+          name: token.name,
+          email: token.email,
+          tenantId: token.tenantId,
+          tenantIds: token.tenantIds,
+        };
+      }
+    }
+
+    if (!user || !user.tenantIds) {
+      console.error("Cannot switch tenant: User information not available");
+      throw new Error("User not authenticated or missing tenant information");
+    }
+
+    // Verify the tenant ID is valid for this user
+    const validTenant = user.tenantIds.find(
+      (t: { tenant_id: string }) => t.tenant_id === credentials.tenantId
+    );
+
+    if (!validTenant) {
+      console.error(`Invalid tenant ID: ${credentials.tenantId}`);
+      throw new Error("Invalid tenant ID for this user");
+    }
+
+    console.log(`Switching to tenant: ${credentials.tenantId}`);
+
+    // if user aleady have keepActiveTenant as prefix - remove it
+    if (user.accessToken.startsWith("keepActiveTenant=")) {
+      user.accessToken = user.accessToken.replace(/keepActiveTenant=\w+&/, "");
+    }
+    // add keepActiveTenant= with the current tenant to user.accessToken
+    user.accessToken = `keepActiveTenant=${credentials.tenantId}&${user.accessToken}`;
+    // Return the user with the new tenant ID
+    return {
+      ...user,
+      tenantId: credentials.tenantId,
+    };
+  },
+});
+
+// Add the tenant switch provider to the config
+// Use type assertion to add the tenant switch provider to the config
+// This bypasses TypeScript's type checking for this specific operation
+config.providers = [...config.providers, tenantSwitchProvider] as any;
 
 function proxyFetch(
   ...args: Parameters<typeof fetch>
@@ -13,9 +84,7 @@ function proxyFetch(
     "Proxy called for URL:",
     args[0] instanceof Request ? args[0].url : args[0]
   );
-
   const dispatcher = new ProxyAgent(proxyUrl!);
-
   if (args[0] instanceof Request) {
     const request = args[0];
     // @ts-expect-error `undici` has a `duplex` option
@@ -29,13 +98,11 @@ function proxyFetch(
       if (isDebug) {
         // Clone the response to log it without consuming the body
         const clonedResponse = response.clone();
-
         console.log("Proxy response status:", clonedResponse.status);
         console.log(
           "Proxy response headers:",
           Object.fromEntries(clonedResponse.headers)
         );
-
         // Log response body only in debug mode
         try {
           const body = await clonedResponse.text();
@@ -47,20 +114,17 @@ function proxyFetch(
       return response;
     });
   }
-
   // @ts-expect-error `undici` has a `duplex` option
   return undici(args[0], { ...(args[1] || {}), dispatcher }).then(
     async (response) => {
       if (isDebug) {
         // Clone the response to log it without consuming the body
         const clonedResponse = response.clone();
-
         console.log("Proxy response status:", clonedResponse.status);
         console.log(
           "Proxy response headers:",
           Object.fromEntries(clonedResponse.headers)
         );
-
         // Log response body only in debug mode
         try {
           const body = await clonedResponse.text();
@@ -77,18 +141,15 @@ function proxyFetch(
 // Modify the config if using Azure AD with proxy
 if (authType === AuthType.AZUREAD && proxyUrl) {
   const provider = config.providers[0] as ReturnType<typeof MicrosoftEntraID>;
-
   if (!proxyUrl) {
     console.log("Proxy is not enabled for Azure AD");
   } else {
     console.log("Proxy is enabled for Azure AD:", proxyUrl);
   }
-
   // Override the `customFetch` symbol in the provider
   provider[customFetch] = async (...args: Parameters<typeof fetch>) => {
     const url = new URL(args[0] instanceof Request ? args[0].url : args[0]);
     console.log("Custom Fetch Intercepted:", url.toString());
-
     // Handle `.well-known/openid-configuration` logic
     if (url.pathname.endsWith(".well-known/openid-configuration")) {
       console.log("Intercepting .well-known/openid-configuration");
@@ -111,11 +172,9 @@ if (authType === AuthType.AZUREAD && proxyUrl) {
       console.log("Modified issuer:", issuer);
       return Response.json({ ...json, issuer });
     }
-
     // Fallback for all other requests
     return proxyFetch(...args);
   };
-
   // Override profile since it uses fetch without customFetch
   provider.profile = async (profile, tokens) => {
     // @tb: this causes 431 Request Header Fields Too Large
@@ -138,7 +197,6 @@ if (authType === AuthType.AZUREAD && proxyUrl) {
     //   }
     // }
     // https://stackoverflow.com/questions/77686104/how-to-resolve-http-error-431-nextjs-next-auth
-
     return {
       id: profile.sub,
       name: profile.name,
@@ -149,6 +207,39 @@ if (authType === AuthType.AZUREAD && proxyUrl) {
   };
 }
 
-console.log("Starting Keep frontend with auth type:", authType);
+// Modify the session callback to ensure tenantIds are available
+const originalSessionCallback = config.callbacks.session;
+config.callbacks.session = async (params) => {
+  const session = await originalSessionCallback(params);
+
+  // Make sure tenantIds from the token are added to the session
+  if (params.token && "tenantIds" in params.token) {
+    session.user.tenantIds = params.token.tenantIds as {
+      tenant_id: string;
+      tenant_name: string;
+    }[];
+  }
+
+  // Also copy tenantIds from user object if available
+  if (params.user && "tenantIds" in params.user) {
+    session.user.tenantIds = params.user.tenantIds;
+  }
+
+  return session;
+};
+
+// Modify the JWT callback to preserve tenantIds
+const originalJwtCallback = config.callbacks.jwt;
+config.callbacks.jwt = async (params) => {
+  const token = await originalJwtCallback(params);
 
+  // Make sure tenantIds from the user are preserved in the token
+  if (params.user && "tenantIds" in params.user) {
+    token.tenantIds = params.user.tenantIds;
+  }
+
+  return token;
+};
+
+console.log("Starting Keep frontend with auth type:", authType);
 export const { handlers, auth, signIn, signOut } = NextAuth(config);
diff --git a/keep-ui/components/navbar/Menu.tsx b/keep-ui/components/navbar/Menu.tsx
index 4555cc0e0f..bebcc5da2b 100644
--- a/keep-ui/components/navbar/Menu.tsx
+++ b/keep-ui/components/navbar/Menu.tsx
@@ -7,6 +7,7 @@ import { AiOutlineMenu, AiOutlineClose } from "react-icons/ai";
 import { usePathname } from "next/navigation";
 import { useLocalStorage } from "utils/hooks/useLocalStorage";
 import { useHotkeys } from "react-hotkeys-hook";
+import { Session } from "next-auth";
 
 type CloseMenuOnRouteChangeProps = {
   closeMenu: () => void;
@@ -24,9 +25,10 @@ const CloseMenuOnRouteChange = ({ closeMenu }: CloseMenuOnRouteChangeProps) => {
 
 type MenuButtonProps = {
   children: ReactNode;
+  session: Session | null;
 };
 
-export const Menu = ({ children }: MenuButtonProps) => {
+export const Menu = ({ children, session }: MenuButtonProps) => {
   const [isMenuMinimized, setisMenuMinimized] = useLocalStorage<boolean>(
     "menu-minimized",
     false
@@ -57,7 +59,10 @@ export const Menu = ({ children }: MenuButtonProps) => {
             className='relative bg-gray-50 col-span-1 border-r border-gray-300 h-full hidden lg:block [&[data-minimized="true"]>nav]:invisible'
             data-minimized={isMenuMinimized}
           >
-            <nav className="flex flex-col h-full">{children}</nav>
+            <nav className="flex flex-col h-full">
+              {/* No more TenantSwitcher - the logo and tenant switching is now in Search component */}
+              {children}
+            </nav>
           </aside>
 
           <CloseMenuOnRouteChange closeMenu={closeMenu} />
@@ -71,7 +76,8 @@ export const Menu = ({ children }: MenuButtonProps) => {
               </Popover.Button>
             </div>
 
-            {children}
+            {/* No more TenantSwitcher here either */}
+            <div className="mt-12">{children}</div>
           </Popover.Panel>
         </>
       )}
diff --git a/keep-ui/components/navbar/Navbar.tsx b/keep-ui/components/navbar/Navbar.tsx
index 64ec664213..ac5c36da10 100644
--- a/keep-ui/components/navbar/Navbar.tsx
+++ b/keep-ui/components/navbar/Navbar.tsx
@@ -12,10 +12,11 @@ import "./Navbar.css";
 
 export default async function NavbarInner() {
   const session = await auth();
+
   return (
     <>
-      <Menu>
-        <Search />
+      <Menu session={session}>
+        <Search session={session} />
         <div className="pt-4 space-y-4 flex-1 overflow-auto scrollable-menu-shadow">
           <IncidentsLinks session={session} />
           <AlertsLinks session={session} />
diff --git a/keep-ui/components/navbar/Search.tsx b/keep-ui/components/navbar/Search.tsx
index ac61e9d3dd..72a65e98b2 100644
--- a/keep-ui/components/navbar/Search.tsx
+++ b/keep-ui/components/navbar/Search.tsx
@@ -4,13 +4,14 @@ import { ElementRef, Fragment, useEffect, useRef, useState } from "react";
 import Image from "next/image";
 import Link from "next/link";
 import { useRouter } from "next/navigation";
-import { Icon, List, ListItem, TextInput, Subtitle } from "@tremor/react";
+import { Icon, List, ListItem, Subtitle } from "@tremor/react";
 import {
   Combobox,
   ComboboxButton,
   ComboboxInput,
   ComboboxOption,
   ComboboxOptions,
+  Popover,
   Transition,
 } from "@headlessui/react";
 import {
@@ -29,6 +30,8 @@ import { LuWorkflow } from "react-icons/lu";
 import { AiOutlineAlert, AiOutlineGroup } from "react-icons/ai";
 import { MdOutlineEngineering, MdOutlineSearchOff } from "react-icons/md";
 import { useConfig } from "utils/hooks/useConfig";
+import { Session } from "next-auth";
+import { signIn } from "next-auth/react";
 import KeepPng from "../../keep.png";
 
 const NAVIGATION_OPTIONS = [
@@ -88,7 +91,11 @@ const NAVIGATION_OPTIONS = [
   },
 ];
 
-export const Search = () => {
+interface SearchProps {
+  session: Session | null;
+}
+
+export const Search = ({ session }: SearchProps) => {
   const [query, setQuery] = useState<string>("");
   const [selectedOption, setSelectedOption] = useState<string | null>(null);
   const router = useRouter();
@@ -96,6 +103,12 @@ export const Search = () => {
   const comboboxInputRef = useRef<ElementRef<"input">>(null);
   const { data: configData } = useConfig();
   const docsUrl = configData?.KEEP_DOCS_URL || "https://docs.keephq.dev";
+  const [isLoading, setIsLoading] = useState(false);
+
+  // Log session for debugging
+  useEffect(() => {
+    console.log("Search component session:", session);
+  }, [session]);
 
   const EXTERNAL_OPTIONS = [
     {
@@ -159,6 +172,31 @@ export const Search = () => {
       )
     : OPTIONS;
 
+  // Tenant switcher function
+  const switchTenant = async (tenantId: string) => {
+    setIsLoading(true);
+    try {
+      // Use the tenant-switch provider to change tenants
+      let sessionAsJson = JSON.stringify(session);
+      const result = await signIn("tenant-switch", {
+        redirect: false,
+        tenantId,
+        sessionAsJson,
+      });
+
+      if (result?.error) {
+        console.error("Error switching tenant:", result.error);
+      } else {
+        // new tenant, let's reload the page
+        window.location.reload();
+      }
+    } catch (error) {
+      console.error("Error switching tenant:", error);
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
   const NoQueriesFoundResult = () => {
     if (query.length && queriedOptions.length === 0) {
       return (
@@ -280,58 +318,133 @@ export const Search = () => {
     if (!isMac()) {
       return;
     }
-    setPlaceholderText("Search or start with ⌘K");
+    setPlaceholderText("Search (or ⌘K)");
   }, []);
 
+  // Check if tenant switching is available - with null/undefined check safety
+  const hasTenantSwitcher =
+    session &&
+    session.user &&
+    session.user.tenantIds &&
+    session.user.tenantIds.length > 1;
+
+  // Get current tenant logo URL if available - this now works even with just one tenant
+  const currentTenant = session?.user?.tenantIds?.find(
+    (tenant) => tenant.tenant_id === session.tenantId
+  );
+  const tenantLogoUrl = currentTenant?.tenant_logo_url;
+  const hasTenantLogo = Boolean(tenantLogoUrl);
+
   return (
-    <div className="flex items-center space-x-3 py-3 px-2 border-b border-gray-300">
-      <Link href="/">
-        <Image className="w-8" src={KeepPng} alt="Keep Logo" />
-      </Link>
+    <div className="flex items-center w-full py-3 px-2 border-b border-gray-300">
+      <div className="flex-shrink-0 flex items-center">
+        {hasTenantSwitcher ? (
+          <Popover className="relative">
+            {({ open }) => (
+              <>
+                <Popover.Button
+                  className="focus:outline-none flex items-center"
+                  disabled={isLoading}
+                >
+                  <Image className="w-8" src={KeepPng} alt="Keep Logo" />
+                  {tenantLogoUrl && (
+                    <Image
+                      src={tenantLogoUrl || ""}
+                      alt={`${currentTenant?.tenant_name || "Tenant"} Logo`}
+                      width={60}
+                      height={60}
+                      className="ml-4 object-cover"
+                    />
+                  )}
+                </Popover.Button>
 
-      <Combobox
-        value={query}
-        onChange={onOptionSelection}
-        as="div"
-        className="relative"
-      >
-        {({ open }) => (
-          <>
-            {open && (
-              <div
-                className="fixed inset-0 bg-black/40 z-10"
-                aria-hidden="true"
-              />
+                <Popover.Panel className="absolute z-10 mt-1 w-48 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
+                  <div className="py-1 divide-y divide-gray-200">
+                    <div className="px-3 py-2 text-xs font-medium text-gray-500">
+                      Switch Tenant
+                    </div>
+                    {session.user.tenantIds?.map((tenant) => (
+                      <button
+                        key={tenant.tenant_id}
+                        className={`block w-full text-left px-4 py-2 text-sm ${
+                          tenant.tenant_id === session.tenantId
+                            ? "bg-orange-50 text-orange-700 font-medium"
+                            : "text-gray-700 hover:bg-gray-50"
+                        }`}
+                        onClick={() => switchTenant(tenant.tenant_id)}
+                        disabled={
+                          tenant.tenant_id === session.tenantId || isLoading
+                        }
+                      >
+                        {tenant.tenant_name}
+                      </button>
+                    ))}
+                  </div>
+                </Popover.Panel>
+              </>
             )}
-            <ComboboxButton ref={comboboxBtnRef}>
-              <ComboboxInput
-                className="z-20 tremor-TextInput-root relative flex items-center min-w-[10rem] outline-none rounded-tremor-default transition duration-100 border shadow-tremor-input dark:shadow-dark-tremor-input bg-tremor-background dark:bg-dark-tremor-background hover:bg-tremor-background-muted dark:hover:bg-dark-tremor-background-muted text-tremor-content dark:text-dark-tremor-content border-tremor-border dark:border-dark-tremor-border tremor-TextInput-input w-full bg-transparent focus:outline-none focus:ring-0 text-tremor-default py-2  [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none pr-3 pl-3 placeholder:text-tremor-content dark:placeholder:text-dark-tremor-content"
-                placeholder={placeholderText}
-                color="orange"
-                value={query}
-                onChange={(event) => setQuery(event.target.value)}
-                ref={comboboxInputRef}
+          </Popover>
+        ) : (
+          <Link href="/" className="flex items-center">
+            <Image className="w-8" src={KeepPng} alt="Keep Logo" />
+            {hasTenantLogo && (
+              <Image
+                src={tenantLogoUrl || ""}
+                alt={`${currentTenant?.tenant_name || "Tenant"} Logo`}
+                width={60}
+                height={60}
+                className="ml-4 object-cover"
               />
-            </ComboboxButton>
-            <Transition
-              as={Fragment}
-              beforeLeave={onLeave}
-              leave="transition ease-in duration-100"
-              leaveFrom="opacity-100"
-              leaveTo="opacity-0"
-            >
-              <ComboboxOptions
-                className="absolute mt-1 max-h-screen overflow-auto rounded-md bg-white shadow-lg ring-1 ring-black/5 focus:outline-none z-20 w-96"
-                as={List}
-              >
-                <NoQueriesFoundResult />
-                <FilteredResults />
-                <DefaultResults />
-              </ComboboxOptions>
-            </Transition>
-          </>
+            )}
+          </Link>
         )}
-      </Combobox>
+      </div>
+
+      <div className="flex-grow ml-4">
+        <Combobox
+          value={query}
+          onChange={onOptionSelection}
+          as="div"
+          className="relative w-full"
+        >
+          {({ open }) => (
+            <>
+              {open && (
+                <div
+                  className="fixed inset-0 bg-black/40 z-10"
+                  aria-hidden="true"
+                />
+              )}
+              <ComboboxButton ref={comboboxBtnRef} className="w-full">
+                <ComboboxInput
+                  className="z-20 tremor-TextInput-root relative flex items-center w-full outline-none rounded-tremor-default transition duration-100 border shadow-tremor-input dark:shadow-dark-tremor-input bg-tremor-background dark:bg-dark-tremor-background hover:bg-tremor-background-muted dark:hover:bg-dark-tremor-background-muted text-tremor-content dark:text-dark-tremor-content border-tremor-border dark:border-dark-tremor-border tremor-TextInput-input bg-transparent focus:outline-none focus:ring-0 text-tremor-default py-2 [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none pr-3 pl-3 placeholder:text-tremor-content dark:placeholder:text-dark-tremor-content"
+                  placeholder={placeholderText}
+                  color="orange"
+                  value={query}
+                  onChange={(event) => setQuery(event.target.value)}
+                  ref={comboboxInputRef}
+                />
+              </ComboboxButton>
+              <Transition
+                as={Fragment}
+                beforeLeave={onLeave}
+                leave="transition ease-in duration-100"
+                leaveFrom="opacity-100"
+                leaveTo="opacity-0"
+              >
+                <ComboboxOptions
+                  className="absolute mt-1 max-h-screen overflow-auto rounded-md bg-white shadow-lg ring-1 ring-black/5 focus:outline-none z-20 w-96"
+                  as={List}
+                >
+                  <NoQueriesFoundResult />
+                  <FilteredResults />
+                  <DefaultResults />
+                </ComboboxOptions>
+              </Transition>
+            </>
+          )}
+        </Combobox>
+      </div>
     </div>
   );
 };
diff --git a/keep-ui/next.config.js b/keep-ui/next.config.js
index 1e83c7ece8..89f8c3046e 100644
--- a/keep-ui/next.config.js
+++ b/keep-ui/next.config.js
@@ -81,6 +81,11 @@ const nextConfig = {
         protocol: "https",
         hostname: "cdn.prod.website-files.com",
       },
+      // Cloudflare Image Delivery
+      {
+        protocol: "https",
+        hostname: "imagedelivery.net",
+      },
     ],
   },
   // compiler is not supported in turbo mode
diff --git a/keep-ui/types/auth.d.ts b/keep-ui/types/auth.d.ts
index dae9cb0a7b..35041ef7cb 100644
--- a/keep-ui/types/auth.d.ts
+++ b/keep-ui/types/auth.d.ts
@@ -23,6 +23,12 @@ declare module "next-auth" {
     email: string;
     accessToken: string;
     tenantId?: string;
+    // a list of {"tenant_id": id, "tenant_name": name} objects
+    tenantIds?: {
+      tenant_id: string;
+      tenant_name: string;
+      tenant_logo_url?: string;
+    }[];
     role?: string;
   }
 }
diff --git a/keep-ui/utils/hooks/usePusher.ts b/keep-ui/utils/hooks/usePusher.ts
index 448a700876..90bef86a7c 100644
--- a/keep-ui/utils/hooks/usePusher.ts
+++ b/keep-ui/utils/hooks/usePusher.ts
@@ -11,9 +11,6 @@ export const useWebsocket = () => {
   const { data: session } = useSession();
   let channelName = `private-${session?.tenantId}`;
 
-  console.log("useWebsocket: Initializing with config:", configData);
-  console.log("useWebsocket: Session:", session);
-
   // TODO: should be in useMemo?
   if (
     PUSHER === null &&
diff --git a/keep/identitymanager/identity_managers/noauth/noauth_authverifier.py b/keep/identitymanager/identity_managers/noauth/noauth_authverifier.py
index aa9a450bbc..be410ce7f9 100644
--- a/keep/identitymanager/identity_managers/noauth/noauth_authverifier.py
+++ b/keep/identitymanager/identity_managers/noauth/noauth_authverifier.py
@@ -16,14 +16,24 @@ class NoAuthVerifier(AuthVerifierBase):
 
     def _verify_bearer_token(self, token: str) -> AuthenticatedEntity:
         try:
-            token_payload = json.loads(token)
-            tenant_id = token_payload["tenant_id"] or SINGLE_TENANT_UUID
-            email = token_payload["user_id"] or SINGLE_TENANT_EMAIL
-            return AuthenticatedEntity(
-                tenant_id=tenant_id,
-                email=email,
-                role=AdminRole.get_name(),
-            )
+            if token.startswith("keepActiveTenant"):
+                active_tenant, token = token.split("&")
+                active_tenant = active_tenant.split("=")[1]
+                tenant_id = active_tenant or SINGLE_TENANT_UUID
+                return AuthenticatedEntity(
+                    tenant_id=tenant_id,
+                    email=SINGLE_TENANT_EMAIL,
+                    role=AdminRole.get_name(),
+                )
+            else:
+                token_payload = json.loads(token)
+                tenant_id = token_payload["tenant_id"] or SINGLE_TENANT_UUID
+                email = token_payload["user_id"] or SINGLE_TENANT_EMAIL
+                return AuthenticatedEntity(
+                    tenant_id=tenant_id,
+                    email=email,
+                    role=AdminRole.get_name(),
+                )
         except Exception:
             return AuthenticatedEntity(
                 tenant_id=SINGLE_TENANT_UUID,
diff --git a/pyproject.toml b/pyproject.toml
index 3d109062ce..e62d6a8d39 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "keep"
-version = "0.39.10"
+version = "0.40.0"
 description = "Alerting. for developers, by developers."
 authors = ["Keep Alerting LTD"]
 packages = [{include = "keep"}]
diff --git a/tests/test_auth_new.py b/tests/test_auth_new.py
new file mode 100644
index 0000000000..c185b920fe
--- /dev/null
+++ b/tests/test_auth_new.py
@@ -0,0 +1,306 @@
+import time
+
+import jwt
+import pytest
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric import rsa
+from fastapi import HTTPException
+
+from keep.identitymanager.authenticatedentity import AuthenticatedEntity
+from keep.identitymanager.identitymanagerfactory import IdentityManagerFactory
+from tests.fixtures.client import client, setup_api_key, test_app  # noqa
+
+
+# Reuse functions from your existing test
+def generate_test_keys():
+    # Generate private key
+    private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
+
+    # Get the private key in PEM format
+    private_pem = private_key.private_bytes(
+        encoding=serialization.Encoding.PEM,
+        format=serialization.PrivateFormat.PKCS8,
+        encryption_algorithm=serialization.NoEncryption(),
+    )
+
+    # Get the public key in PEM format
+    public_key = private_key.public_key()
+    public_pem = public_key.public_bytes(
+        encoding=serialization.Encoding.PEM,
+        format=serialization.PublicFormat.SubjectPublicKeyInfo,
+    )
+
+    return private_pem, public_pem
+
+
+# Mock classes from your existing test
+class MockSigningKey:
+    def __init__(self, key):
+        self.key = key
+
+
+class MockJWKSClient:
+    def __init__(self, public_key):
+        self.public_key = public_key
+
+    def get_signing_key_from_jwt(self, token):
+        # We need to extract the actual JWT part if it has keepActiveTenant prefix
+        if token.startswith("keepActiveTenant"):
+            _, token = token.split("&")
+
+        return MockSigningKey(key=self.public_key)
+
+
+@pytest.mark.parametrize(
+    "test_app",
+    [
+        {
+            "AUTH_TYPE": "AUTH0",
+            "AUTH0_DOMAIN": "test-domain.auth0.com",
+            "AUTH0_AUDIENCE": "test-audience",
+        },
+    ],
+    indirect=True,
+)
+def test_auth0_with_active_tenant_success(db_session, client, test_app):
+    """Tests Auth0 authentication with keepActiveTenant parameter when tenant is in the token"""
+
+    # Generate test keys
+    private_key_pem, public_key_pem = generate_test_keys()
+
+    # Create payload with multiple tenant IDs
+    tenant_1 = "tenant-1"
+    tenant_2 = "tenant-2"
+
+    payload = {
+        "iss": "https://test-domain.auth0.com/",
+        "sub": "test-user-id",
+        "aud": "test-audience",
+        "exp": int(time.time()) + 3600,
+        "iat": int(time.time()),
+        # Note: We're not setting keep_tenant_id here since we're using keep_tenant_ids
+        "keep_tenant_ids": [{"tenant_id": tenant_1}, {"tenant_id": tenant_2}],
+        "keep_role": "admin",
+        "email": "test@example.com",
+    }
+
+    # Sign the JWT with our private key
+    token = jwt.encode(
+        payload, private_key_pem, algorithm="RS256", headers={"kid": "test-key-id"}
+    )
+
+    # Prepend the keepActiveTenant parameter to use tenant_1
+    active_tenant_token = f"keepActiveTenant={tenant_1}&{token}"
+
+    # Create a mock JWKS client with our public key
+    mock_jwks_client = MockJWKSClient(public_key_pem)
+
+    # Patch the jwks_client in the auth0_authverifier module
+    from ee.identitymanager.identity_managers.auth0.auth0_authverifier import (
+        jwks_client,
+    )
+
+    # Save the original to restore later
+    original_jwks_client = jwks_client
+
+    try:
+        # Replace the module-level client with our mock
+        import ee.identitymanager.identity_managers.auth0.auth0_authverifier
+
+        ee.identitymanager.identity_managers.auth0.auth0_authverifier.jwks_client = (
+            mock_jwks_client
+        )
+
+        # Get the auth verifier
+        auth_verifier = IdentityManagerFactory.get_auth_verifier([])
+
+        # Call the auth verifier with our active tenant token
+        result = auth_verifier(
+            token=active_tenant_token, api_key=None, authorization=None, request=None
+        )
+
+        # Assert authentication was successful with the specified active tenant
+        assert result is not None
+        assert isinstance(result, AuthenticatedEntity)
+        assert result.tenant_id == tenant_1
+        assert result.email == "test@example.com"
+        assert result.role == "admin"
+
+    finally:
+        # Restore the original jwks_client
+        ee.identitymanager.identity_managers.auth0.auth0_authverifier.jwks_client = (
+            original_jwks_client
+        )
+
+
+@pytest.mark.parametrize(
+    "test_app",
+    [
+        {
+            "AUTH_TYPE": "AUTH0",
+            "AUTH0_DOMAIN": "test-domain.auth0.com",
+            "AUTH0_AUDIENCE": "test-audience",
+        },
+    ],
+    indirect=True,
+)
+def test_auth0_with_unauthorized_active_tenant(db_session, client, test_app):
+    """Tests Auth0 authentication with keepActiveTenant parameter when tenant is NOT in the token"""
+
+    # Generate test keys
+    private_key_pem, public_key_pem = generate_test_keys()
+
+    # Create payload with tenant IDs that don't include our target tenant
+    authorized_tenant = "authorized-tenant"
+    unauthorized_tenant = "unauthorized-tenant"
+
+    payload = {
+        "iss": "https://test-domain.auth0.com/",
+        "sub": "test-user-id",
+        "aud": "test-audience",
+        "exp": int(time.time()) + 3600,
+        "iat": int(time.time()),
+        "keep_tenant_ids": [{"tenant_id": authorized_tenant}],
+        "keep_role": "admin",
+        "email": "test@example.com",
+    }
+
+    # Sign the JWT with our private key
+    token = jwt.encode(
+        payload, private_key_pem, algorithm="RS256", headers={"kid": "test-key-id"}
+    )
+
+    # Prepend the keepActiveTenant parameter with an unauthorized tenant
+    active_tenant_token = f"keepActiveTenant={unauthorized_tenant}&{token}"
+
+    # Create a mock JWKS client with our public key
+    mock_jwks_client = MockJWKSClient(public_key_pem)
+
+    # Patch the jwks_client in the auth0_authverifier module
+    from ee.identitymanager.identity_managers.auth0.auth0_authverifier import (
+        jwks_client,
+    )
+
+    # Save the original to restore later
+    original_jwks_client = jwks_client
+
+    try:
+        # Replace the module-level client with our mock
+        import ee.identitymanager.identity_managers.auth0.auth0_authverifier
+
+        ee.identitymanager.identity_managers.auth0.auth0_authverifier.jwks_client = (
+            mock_jwks_client
+        )
+
+        # Get the auth verifier
+        auth_verifier = IdentityManagerFactory.get_auth_verifier([])
+
+        # Call the auth verifier with our unauthorized active tenant token
+        # This should raise an HTTPException with status code 401
+        with pytest.raises(HTTPException) as exc_info:
+            auth_verifier(
+                token=active_tenant_token,
+                api_key=None,
+                authorization=None,
+                request=None,
+            )
+
+        # Verify that the error is what we expect
+        assert exc_info.value.status_code == 401
+        assert "Token does not contain the active tenant" in exc_info.value.detail
+
+    finally:
+        # Restore the original jwks_client
+        ee.identitymanager.identity_managers.auth0.auth0_authverifier.jwks_client = (
+            original_jwks_client
+        )
+
+
+@pytest.mark.parametrize(
+    "test_app",
+    [
+        {
+            "AUTH_TYPE": "AUTH0",
+            "AUTH0_DOMAIN": "test-domain.auth0.com",
+            "AUTH0_AUDIENCE": "test-audience",
+        },
+    ],
+    indirect=True,
+)
+def test_auth0_switching_between_tenants(db_session, client, test_app):
+    """Tests Auth0 authentication with switching between different active tenants"""
+
+    # Generate test keys
+    private_key_pem, public_key_pem = generate_test_keys()
+
+    # Create payload with multiple tenant IDs
+    tenant_1 = "tenant-1"
+    tenant_2 = "tenant-2"
+
+    payload = {
+        "iss": "https://test-domain.auth0.com/",
+        "sub": "test-user-id",
+        "aud": "test-audience",
+        "exp": int(time.time()) + 3600,
+        "iat": int(time.time()),
+        "keep_tenant_ids": [{"tenant_id": tenant_1}, {"tenant_id": tenant_2}],
+        "keep_role": "admin",
+        "email": "test@example.com",
+    }
+
+    # Sign the JWT with our private key
+    token = jwt.encode(
+        payload, private_key_pem, algorithm="RS256", headers={"kid": "test-key-id"}
+    )
+
+    # Create tokens for both tenants
+    tenant_1_token = f"keepActiveTenant={tenant_1}&{token}"
+    tenant_2_token = f"keepActiveTenant={tenant_2}&{token}"
+
+    # Create a mock JWKS client with our public key
+    mock_jwks_client = MockJWKSClient(public_key_pem)
+
+    # Patch the jwks_client in the auth0_authverifier module
+    from ee.identitymanager.identity_managers.auth0.auth0_authverifier import (
+        jwks_client,
+    )
+
+    # Save the original to restore later
+    original_jwks_client = jwks_client
+
+    try:
+        # Replace the module-level client with our mock
+        import ee.identitymanager.identity_managers.auth0.auth0_authverifier
+
+        ee.identitymanager.identity_managers.auth0.auth0_authverifier.jwks_client = (
+            mock_jwks_client
+        )
+
+        # Get the auth verifier
+        auth_verifier = IdentityManagerFactory.get_auth_verifier([])
+
+        # Test with tenant_1
+        result_1 = auth_verifier(
+            token=tenant_1_token, api_key=None, authorization=None, request=None
+        )
+
+        # Assert authentication was successful with tenant_1
+        assert result_1 is not None
+        assert isinstance(result_1, AuthenticatedEntity)
+        assert result_1.tenant_id == tenant_1
+
+        # Now test with tenant_2
+        result_2 = auth_verifier(
+            token=tenant_2_token, api_key=None, authorization=None, request=None
+        )
+
+        # Assert authentication was successful with tenant_2
+        assert result_2 is not None
+        assert isinstance(result_2, AuthenticatedEntity)
+        assert result_2.tenant_id == tenant_2
+
+    finally:
+        # Restore the original jwks_client
+        ee.identitymanager.identity_managers.auth0.auth0_authverifier.jwks_client = (
+            original_jwks_client
+        )