feat(front): basic next auth configuration done
This commit is contained in:
1
front/src/app/(home)/layout.tsx
Normal file
1
front/src/app/(home)/layout.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export { ApplicationLayout as default } from "@/modules/common/layouts/application.layout";
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
6
front/src/app/api/auth/[...nextauth]/route.ts
Normal file
6
front/src/app/api/auth/[...nextauth]/route.ts
Normal 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 };
|
||||
@@ -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";
|
||||
|
||||
30
front/src/modules/auth/components/sign-in.widget.tsx
Normal file
30
front/src/modules/auth/components/sign-in.widget.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
52
front/src/modules/auth/configs/auth.options.ts
Normal file
52
front/src/modules/auth/configs/auth.options.ts
Normal 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;
|
||||
},
|
||||
},
|
||||
};
|
||||
8
front/src/modules/auth/providers/auth.provider.tsx
Normal file
8
front/src/modules/auth/providers/auth.provider.tsx
Normal 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>;
|
||||
};
|
||||
28
front/src/modules/auth/types/next-auth.d.ts
vendored
Normal file
28
front/src/modules/auth/types/next-auth.d.ts
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
8
front/src/modules/common/layouts/application.layout.tsx
Normal file
8
front/src/modules/common/layouts/application.layout.tsx
Normal 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>;
|
||||
};
|
||||
19
front/src/modules/common/layouts/root.layout.tsx
Normal file
19
front/src/modules/common/layouts/root.layout.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
10
front/src/modules/common/providers/application.provider.tsx
Normal file
10
front/src/modules/common/providers/application.provider.tsx
Normal 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>;
|
||||
};
|
||||
Reference in New Issue
Block a user