feat: add logout redirect url (#954)

* feat: add logout redirect url

* fix: format issue
This commit is contained in:
Meier Lukas
2024-08-09 19:24:07 +02:00
committed by GitHub
parent 67195c6051
commit 13e09968d9
5 changed files with 34 additions and 5 deletions

View File

@@ -1,19 +1,38 @@
"use client";
import { createContext, useContext, useEffect } from "react";
import type { PropsWithChildren } from "react";
import { useEffect } from "react";
import dayjs from "dayjs";
import type { Session } from "@homarr/auth";
import { SessionProvider, signIn } from "@homarr/auth/client";
interface AuthProviderProps {
interface AuthProviderProps extends AuthContextProps {
session: Session | null;
}
export const AuthProvider = ({ children, session }: PropsWithChildren<AuthProviderProps>) => {
export const AuthProvider = ({ children, session, logoutUrl }: PropsWithChildren<AuthProviderProps>) => {
useLoginRedirectOnSessionExpiry(session);
return <SessionProvider session={session}>{children}</SessionProvider>;
return (
<SessionProvider session={session}>
<AuthContext.Provider value={{ logoutUrl }}>{children}</AuthContext.Provider>
</SessionProvider>
);
};
interface AuthContextProps {
logoutUrl: string | undefined;
}
const AuthContext = createContext<AuthContextProps | null>(null);
export const useAuthContext = () => {
const context = useContext(AuthContext);
if (!context) throw new Error("useAuthContext must be used within an AuthProvider");
return context;
};
const useLoginRedirectOnSessionExpiry = (session: Session | null) => {

View File

@@ -8,6 +8,7 @@ import "~/styles/scroll-area.scss";
import { ColorSchemeScript, createTheme, MantineProvider } from "@mantine/core";
import { env } from "@homarr/auth/env.mjs";
import { auth } from "@homarr/auth/next";
import { ModalProvider } from "@homarr/modals";
import { Notifications } from "@homarr/notifications";
@@ -56,7 +57,7 @@ export default function Layout(props: { children: React.ReactNode; params: { loc
const StackedProvider = composeWrappers([
async (innerProps) => {
const session = await auth();
return <AuthProvider session={session} {...innerProps} />;
return <AuthProvider session={session} logoutUrl={env.AUTH_LOGOUT_REDIRECT_URL} {...innerProps} />;
},
(innerProps) => <JotaiProvider {...innerProps} />,
(innerProps) => <TRPCReactProvider {...innerProps} />,

View File

@@ -23,6 +23,7 @@ import { useScopedI18n } from "@homarr/translation/client";
import "flag-icons/css/flag-icons.min.css";
import { useAuthContext } from "~/app/[locale]/_client-providers/session";
import { LanguageCombobox } from "./language/language-combobox";
interface UserAvatarMenuProps {
@@ -40,6 +41,7 @@ export const UserAvatarMenu = ({ children }: UserAvatarMenuProps) => {
const session = useSession();
const router = useRouter();
const { logoutUrl } = useAuthContext();
const { openModal } = useModalAction(LogoutModal);
const handleSignout = useCallback(async () => {
@@ -48,6 +50,10 @@ export const UserAvatarMenu = ({ children }: UserAvatarMenuProps) => {
});
openModal({
onTimeout: () => {
if (logoutUrl) {
window.location.assign(logoutUrl);
return;
}
router.refresh();
},
});

View File

@@ -62,6 +62,7 @@ const authProviders = skipValidation ? [] : authProvidersSchema.parse(process.en
export const env = createEnv({
server: {
AUTH_LOGOUT_REDIRECT_URL: z.string().url().optional(),
AUTH_SESSION_EXPIRY_TIME: createDurationSchema("30d"),
AUTH_SECRET: process.env.NODE_ENV === "production" ? z.string().min(1) : z.string().min(1).optional(),
AUTH_PROVIDERS: authProvidersSchema,
@@ -94,6 +95,7 @@ export const env = createEnv({
},
client: {},
runtimeEnv: {
AUTH_LOGOUT_REDIRECT_URL: process.env.AUTH_LOGOUT_REDIRECT_URL,
AUTH_SESSION_EXPIRY_TIME: process.env.AUTH_SESSION_EXPIRY_TIME,
AUTH_SECRET: process.env.AUTH_SECRET,
AUTH_PROVIDERS: process.env.AUTH_PROVIDERS,

View File

@@ -22,6 +22,7 @@
"AUTH_LDAP_USER_MAIL_ATTRIBUTE",
"AUTH_LDAP_USERNAME_FILTER_EXTRA_ARG",
"AUTH_OIDC_AUTO_LOGIN",
"AUTH_LOGOUT_REDIRECT_URL",
"AUTH_PROVIDERS",
"AUTH_SECRET",
"AUTH_SESSION_EXPIRY_TIME",