feat(front): basic next auth configuration done

This commit is contained in:
2024-07-21 00:31:04 +02:00
parent 049e063d48
commit f61bdac457
17 changed files with 333 additions and 29 deletions

View File

@@ -0,0 +1 @@
export { ApplicationLayout as default } from "@/modules/common/layouts/application.layout";

View File

@@ -1,3 +1,4 @@
import { SignInWidget } from "@/modules/auth/components/sign-in.widget";
import ThemeSwitcher from "@/modules/common/theme-switcher";
export default function Home() {
@@ -5,6 +6,7 @@ export default function Home() {
<main>
Main page
<ThemeSwitcher />
<SignInWidget />
</main>
);
}

View File

@@ -0,0 +1,6 @@
import { authOptions } from "@/modules/auth/configs/auth.options";
import NextAuth from "next-auth";
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

View File

@@ -1,22 +1 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "@/styles/main.scss";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Personal finance - Home",
description: "Manage your money blablabla",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}
export { RootLayout as default } from "@/modules/common/layouts/root.layout";

View File

@@ -0,0 +1,30 @@
"use client";
import { signIn, useSession } from "next-auth/react";
export const SignInWidget = () => {
const { data } = useSession();
return (
<div>
<button
onClick={async () => {
const result = await signIn("credentials", {
redirect: false,
username: "dqnid",
password: "1234",
callbackUrl: "/",
});
console.debug("Login result:", result);
if (result?.error === "CredentialsSignin") {
return "Invalid credentials";
}
}}
>
LOGIN
</button>
{JSON.stringify(data)}
</div>
);
};

View File

@@ -0,0 +1,52 @@
import { AuthOptions, User } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
export const authOptions: AuthOptions = {
session: {
strategy: "jwt",
},
pages: {
signIn: "/auth/sign-in",
},
providers: [
CredentialsProvider({
name: "Sign in",
credentials: {
username: { label: "Username", type: "text", placeholder: "yourself" },
password: { label: "Password", type: "password" },
},
async authorize(credentials, req) {
console.log("__credentials", credentials);
const user: User = {
id: credentials?.password ?? "asdf",
role: "admin",
image: "none",
name: credentials?.username,
apiSession: {
accessToken: credentials?.password ?? "asdf",
},
};
return user;
},
}),
],
callbacks: {
async jwt({ token, user }) {
// Persist the OAuth access_token to the token right after signin
if (user) {
const { apiSession, ...cleanedUser } = user;
token.user = cleanedUser;
token.apiSession = apiSession;
}
return token;
},
async session({ session, token }) {
// Send properties to the client, like an access_token from a provider.
if (token?.user && session) {
session.apiSession = token.apiSession;
session.user = token.user;
}
return session;
},
},
};

View File

@@ -0,0 +1,8 @@
"use client";
import { SessionProvider } from "next-auth/react";
import { PropsWithChildren } from "react";
export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
return <SessionProvider>{children}</SessionProvider>;
};

View File

@@ -0,0 +1,28 @@
import NextAuth, { DefaultSession } from "next-auth";
import { JWT, DefaultJWT } from "next-auth/jwt";
declare module "next-auth" {
type Role = "user" | "admin";
interface ApiSession {
accessToken: string;
refreshToken?: string;
}
interface User {
id: string;
role: Role;
image?: string;
name?: string;
apiSession?: ApiSession;
}
interface Session extends DefaultSession {
apiSession?: ApiSession;
}
}
declare module "next-auth/jwt" {
interface JWT {
user?: Omit<User, "apiSession">;
apiSession?: ApiSession;
}
}

View File

@@ -0,0 +1,8 @@
import { PropsWithChildren } from "react";
import { ApplicationProvider } from "../providers/application.provider";
export const ApplicationLayout: React.FC<PropsWithChildren> = ({
children,
}) => {
return <ApplicationProvider>{children}</ApplicationProvider>;
};

View File

@@ -0,0 +1,19 @@
import type { Metadata } from "next";
import "@/styles/main.scss";
export const metadata: Metadata = {
title: "Personal finance - Home",
description: "Manage your money blablabla",
};
export function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

View File

@@ -0,0 +1,10 @@
"use client";
import { AuthProvider } from "@/modules/auth/providers/auth.provider";
import { PropsWithChildren } from "react";
export const ApplicationProvider: React.FC<PropsWithChildren> = ({
children,
}) => {
return <AuthProvider>{children}</AuthProvider>;
};