From 33552f5603292abbc2b750d9872d23ab634ccb4a Mon Sep 17 00:00:00 2001 From: Natanael Filho Date: Tue, 30 Jul 2024 00:35:42 -0300 Subject: [PATCH 1/4] fixing credentials login --- .env.dev | 13 +- package-lock.json | 157 +++++++++++------- package.json | 10 +- src/actions/auth.actions.ts | 18 -- src/app/(auth)/login/page.tsx | 7 +- src/app/(auth)/oauth/page.tsx | 7 - src/app/admin/page.tsx | 2 +- src/app/api/auth/[...nextauth]/route.ts | 8 +- src/app/components/ClientLayout.tsx | 38 ----- .../components/buttons/appleAuth.button.tsx | 1 - .../components/buttons/googleAuth.button.tsx | 36 ++-- .../buttons/microsoftAuth.button.tsx | 1 - src/app/components/buttons/singOut.button.tsx | 21 ++- src/app/components/clientLayout.tsx | 32 ++++ src/app/components/forms/signInForm.tsx | 24 ++- .../{loginForm.tsx => login.component.tsx} | 4 +- .../{AppBar.tsx => navBar.component.tsx} | 10 +- .../{Sidebar.tsx => sidebar.component.tsx} | 14 +- src/app/home/page.tsx | 18 ++ src/app/layout.tsx | 8 +- src/app/page.tsx | 30 ++-- src/auth.ts | 25 ++- src/middleware.ts | 5 - src/services/user.service.ts | 7 - tsconfig.json | 1 - 25 files changed, 261 insertions(+), 236 deletions(-) delete mode 100644 src/actions/auth.actions.ts delete mode 100644 src/app/components/ClientLayout.tsx create mode 100644 src/app/components/clientLayout.tsx rename src/app/components/{loginForm.tsx => login.component.tsx} (92%) rename src/app/components/{AppBar.tsx => navBar.component.tsx} (79%) rename src/app/components/{Sidebar.tsx => sidebar.component.tsx} (82%) create mode 100644 src/app/home/page.tsx delete mode 100644 src/middleware.ts diff --git a/.env.dev b/.env.dev index 1909c6f..6f14e10 100644 --- a/.env.dev +++ b/.env.dev @@ -1,4 +1,9 @@ -PORT=4000 -NEXT_PUBLIC_API_URL="http://localhost:3000" -GOOGLE_CLIENT_ID="" -GOOGLE_CLIENT_SECRET="" \ No newline at end of file +NEXT_PUBLIC_API_URL= +NEXTAUTH_URL= +NEXTAUTH_SECRET= +JWT_SECRET= +GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_SECRET= +MICROSOFT_CLIENT_ID= +MICROSOFT_CLIENT_SECRET= +MICROSOFT_TENANT_ID= \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 01e0a50..1c7ec8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "dotenv": "^16.4.5", "jsonwebtoken": "^9.0.2", "next": "^14.2.5", - "next-auth": "^5.0.0-beta.20", + "next-auth": "^4.24.7", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.52.1", @@ -74,36 +74,6 @@ "node": ">=6.0.0" } }, - "node_modules/@auth/core": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.34.2.tgz", - "integrity": "sha512-KywHKRgLiF3l7PLyL73fjLSIBe1YNcA6sMeew4yMP6cfCWGXZrkkXd32AjRi1hlJ9nvovUBGZHvbn+LijO6ZeQ==", - "dependencies": { - "@panva/hkdf": "^1.1.1", - "@types/cookie": "0.6.0", - "cookie": "0.6.0", - "jose": "^5.1.3", - "oauth4webapi": "^2.10.4", - "preact": "10.11.3", - "preact-render-to-string": "5.2.3" - }, - "peerDependencies": { - "@simplewebauthn/browser": "^9.0.1", - "@simplewebauthn/server": "^9.0.2", - "nodemailer": "^6.8.0" - }, - "peerDependenciesMeta": { - "@simplewebauthn/browser": { - "optional": true - }, - "@simplewebauthn/server": { - "optional": true - }, - "nodemailer": { - "optional": true - } - } - }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -2114,7 +2084,8 @@ "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==" + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true }, "node_modules/@types/graceful-fs": { "version": "4.1.9", @@ -6264,9 +6235,9 @@ } }, "node_modules/jose": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.6.3.tgz", - "integrity": "sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g==", + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", + "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", "funding": { "url": "https://github.com/sponsors/panva" } @@ -6745,31 +6716,40 @@ } }, "node_modules/next-auth": { - "version": "5.0.0-beta.20", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.20.tgz", - "integrity": "sha512-+48SjV9k9AtUU3JbEIa4PXNjKIewfFjVGL7Xs2RKkuQ5QqegDNIQiIG8sLk6/qo7RTScQYIGKgeQ5IuQRtrTQg==", - "dependencies": { - "@auth/core": "0.34.2" + "version": "4.24.7", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.7.tgz", + "integrity": "sha512-iChjE8ov/1K/z98gdKbn2Jw+2vLgJtVV39X+rCP5SGnVQuco7QOr19FRNGMIrD8d3LYhHWV9j9sKLzq1aDWWQQ==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@panva/hkdf": "^1.0.2", + "cookie": "^0.5.0", + "jose": "^4.15.5", + "oauth": "^0.9.15", + "openid-client": "^5.4.0", + "preact": "^10.6.3", + "preact-render-to-string": "^5.1.19", + "uuid": "^8.3.2" }, "peerDependencies": { - "@simplewebauthn/browser": "^9.0.1", - "@simplewebauthn/server": "^9.0.2", - "next": "^14.0.0-0 || ^15.0.0-0", + "next": "^12.2.5 || ^13 || ^14", "nodemailer": "^6.6.5", - "react": "^18.2.0 || ^19.0.0-0" + "react": "^17.0.2 || ^18", + "react-dom": "^17.0.2 || ^18" }, "peerDependenciesMeta": { - "@simplewebauthn/browser": { - "optional": true - }, - "@simplewebauthn/server": { - "optional": true - }, "nodemailer": { "optional": true } } }, + "node_modules/next-auth/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -6839,13 +6819,10 @@ "node": ">=8" } }, - "node_modules/oauth4webapi": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.11.1.tgz", - "integrity": "sha512-aNzOnL98bL6izG97zgnZs1PFEyO4WDVRhz2Pd066NPak44w5ESLRCYmJIyey8avSBPOMtBjhF3ZDDm7bIb7UOg==", - "funding": { - "url": "https://github.com/sponsors/panva" - } + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" }, "node_modules/object-assign": { "version": "4.1.1", @@ -6982,6 +6959,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oidc-token-hash": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", + "integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==", + "engines": { + "node": "^10.13.0 || >=12.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -7006,6 +6991,44 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openid-client": { + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.6.5.tgz", + "integrity": "sha512-5P4qO9nGJzB5PI0LFlhj4Dzg3m4odt0qsJTfyEtZyOlkgpILwEioOhVVJOrS1iVH494S4Ee5OCjjg6Bf5WOj3w==", + "dependencies": { + "jose": "^4.15.5", + "lru-cache": "^6.0.0", + "object-hash": "^2.2.0", + "oidc-token-hash": "^5.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/openid-client/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/openid-client/node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/openid-client/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -7410,18 +7433,18 @@ "dev": true }, "node_modules/preact": { - "version": "10.11.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz", - "integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==", + "version": "10.23.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.23.1.tgz", + "integrity": "sha512-O5UdRsNh4vdZaTieWe3XOgSpdMAmkIYBCT3VhQDlKrzyCm8lUYsk0fmVEvoQQifoOjFRTaHZO69ylrzTW2BH+A==", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" } }, "node_modules/preact-render-to-string": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz", - "integrity": "sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==", + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz", + "integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==", "dependencies": { "pretty-format": "^3.8.0" }, @@ -8851,6 +8874,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/package.json b/package.json index ac23d39..972ebbe 100644 --- a/package.json +++ b/package.json @@ -14,19 +14,19 @@ "dependencies": { "@emotion/react": "^11.13.0", "@emotion/styled": "^11.13.0", - "@hookform/resolvers": "^3.9.0", - "@tanstack/react-query": "^5.51.11", - "axios": "^1.7.2", - "cookie": "^0.6.0", "@fortawesome/free-solid-svg-icons": "^6.6.0", "@fortawesome/react-fontawesome": "^0.2.2", "@heroicons/react": "^2.1.5", + "@hookform/resolvers": "^3.9.0", "@mui/icons-material": "^5.16.5", "@mui/material": "^5.16.5", + "@tanstack/react-query": "^5.51.11", + "axios": "^1.7.2", + "cookie": "^0.6.0", "dotenv": "^16.4.5", "jsonwebtoken": "^9.0.2", "next": "^14.2.5", - "next-auth": "^5.0.0-beta.20", + "next-auth": "^4.24.7", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.52.1", diff --git a/src/actions/auth.actions.ts b/src/actions/auth.actions.ts deleted file mode 100644 index 7defb00..0000000 --- a/src/actions/auth.actions.ts +++ /dev/null @@ -1,18 +0,0 @@ -'use server'; -import { signIn, signOut } from '@/auth'; - -export async function signInEmailPassword(data: any) { - return await signIn('credentials', { - email: data.email, - password: data.password, - redirect: false, - }); -} - -export async function authGoogle() { - return await signIn('google'); -} - -export async function endSession() { - return await signOut(); -} diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index 1ec9e1c..b46adc6 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -3,10 +3,7 @@ import { Box } from '@mui/material'; import Image from 'next/image'; import calcuclusLogo from '@/public/calculus-logo.svg'; -import LoginForm from '@/app/components/loginForm'; -import { auth } from '@/auth'; -import { useEffect } from 'react'; -import { toast } from 'react-toastify'; +import LoginComponent from '@/app/components/login.component'; export default async function LoginPage() { return ( @@ -22,7 +19,7 @@ export default async function LoginPage() { />

Login

- + ); diff --git a/src/app/(auth)/oauth/page.tsx b/src/app/(auth)/oauth/page.tsx index f4b76f7..8ee699c 100644 --- a/src/app/(auth)/oauth/page.tsx +++ b/src/app/(auth)/oauth/page.tsx @@ -1,11 +1,4 @@ -import { useRouter } from 'next/router'; -import { useEffect } from 'react'; -import { signIn } from 'next-auth/react'; - export default function OAuth() { - const router = useRouter(); - const { accessToken } = router.query; - // useEffect(() => { // if (accessToken) { // signIn('google', { callbackUrl: '/your-redirect-url', accessToken }); diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 60def4e..4a0002c 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import Layout from '../components/ClientLayout'; +import Layout from '../components/clientLayout'; import React, { useState, useEffect } from 'react'; import { Box } from '@mui/material'; import SearchBar from '../components/admin/SearchBar'; diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index 0aa1cd7..c5d8789 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -1,2 +1,6 @@ -import { handlers } from '@/auth'; -export const { GET, POST } = handlers; +import { authOptions } from '@/auth'; +import NextAuth from 'next-auth/next'; + +const handler = NextAuth(authOptions); + +export { handler as GET, handler as POST }; diff --git a/src/app/components/ClientLayout.tsx b/src/app/components/ClientLayout.tsx deleted file mode 100644 index 87c5c28..0000000 --- a/src/app/components/ClientLayout.tsx +++ /dev/null @@ -1,38 +0,0 @@ -'use client'; - -import React, { useState } from 'react'; -import { useRouter } from 'next/router'; -import MyAppBar from './AppBar'; -import Sidebar from './Sidebar'; -import { Box, Toolbar } from '@mui/material'; - -export default function ClientLayout({ - children, -}: { - children: React.ReactNode; -}) { - // const [sidebarOpen, setSidebarOpen] = useState(false); - // const router = useRouter(); - // const { pathname } = router; - - // const handleDrawerOpen = () => { - // setSidebarOpen(!sidebarOpen); - // }; - - // const handleDrawerClose = () => { - // setSidebarOpen(false); - // }; - - // const isAuthPage = pathname === '/login' || pathname === '/signup'; - - return ( - - {/* {!isAuthPage && } */} - {/* {!isAuthPage && } */} - - - {children} - - - ); -} diff --git a/src/app/components/buttons/appleAuth.button.tsx b/src/app/components/buttons/appleAuth.button.tsx index 886dba8..024b342 100644 --- a/src/app/components/buttons/appleAuth.button.tsx +++ b/src/app/components/buttons/appleAuth.button.tsx @@ -2,7 +2,6 @@ import Image from 'next/image'; import appleIcon from '@/public/apple.svg'; -import { signIn } from '@/auth'; import { Button } from '@mui/material'; export function AppleAuthButton() { diff --git a/src/app/components/buttons/googleAuth.button.tsx b/src/app/components/buttons/googleAuth.button.tsx index bd8de89..7df2226 100644 --- a/src/app/components/buttons/googleAuth.button.tsx +++ b/src/app/components/buttons/googleAuth.button.tsx @@ -3,28 +3,26 @@ import Image from 'next/image'; import googleIcon from '@/public/google.svg'; import { Box, Button } from '@mui/material'; -import { authGoogle } from '@/actions/auth.actions'; +import { signIn } from 'next-auth/react'; export function GoogleAuthButton() { + const handleClick = () => { + signIn('google'); + }; + return ( - { - authGoogle(); - }} + - + Google + ); } diff --git a/src/app/components/buttons/microsoftAuth.button.tsx b/src/app/components/buttons/microsoftAuth.button.tsx index bf5c366..ee1c39e 100644 --- a/src/app/components/buttons/microsoftAuth.button.tsx +++ b/src/app/components/buttons/microsoftAuth.button.tsx @@ -2,7 +2,6 @@ import Image from 'next/image'; import microsoftIcon from '@/public/microsoft.svg'; -import { signIn } from '@/auth'; import { Button } from '@mui/material'; export function MicrosoftAuthButton() { diff --git a/src/app/components/buttons/singOut.button.tsx b/src/app/components/buttons/singOut.button.tsx index db30115..0a949d9 100644 --- a/src/app/components/buttons/singOut.button.tsx +++ b/src/app/components/buttons/singOut.button.tsx @@ -1,13 +1,20 @@ 'use client'; -import { signIn, signOut } from '@/auth'; -import { userSignOut } from '@/services/user.service'; -import { Button } from '@mui/material'; +import { Box, Button } from '@mui/material'; +import { signOut } from 'next-auth/react'; export function SignOutButton() { - const handle = () => { - userSignOut(); + const handleClick = () => { + signOut(); + window.location.href = '/'; }; - - return ; + return ( + + ); } diff --git a/src/app/components/clientLayout.tsx b/src/app/components/clientLayout.tsx new file mode 100644 index 0000000..e7aa1e6 --- /dev/null +++ b/src/app/components/clientLayout.tsx @@ -0,0 +1,32 @@ +'use client'; + +import React, { useState } from 'react'; +import { useRouter } from 'next/router'; +import NavBar from './navBar.component'; +import Sidebar from './sidebar.component'; +import { Box, Toolbar } from '@mui/material'; +import { useSession } from 'next-auth/react'; + +export default function ClientLayout({ + children, +}: { + children: React.ReactNode; +}) { + const session = useSession(); + const [sidebarOpen, setSidebarOpen] = useState(false); + const handleDrawerOpen = () => { + setSidebarOpen(!sidebarOpen); + }; + + const handleDrawerClose = () => { + setSidebarOpen(false); + }; + + return ( + + {session.data && } + {session.data && } + {children} + + ); +} diff --git a/src/app/components/forms/signInForm.tsx b/src/app/components/forms/signInForm.tsx index 4396cd2..71e0bc9 100644 --- a/src/app/components/forms/signInForm.tsx +++ b/src/app/components/forms/signInForm.tsx @@ -11,18 +11,27 @@ import { import { useForm, SubmitHandler } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { SigninData, signinSchema } from '@/lib/schemas/singin.schemas'; -import { SignInResponse } from 'next-auth/react'; -import { useSearchParams } from 'next/navigation'; import { toast } from 'react-toastify'; import { useRouter } from 'next/router'; -import { signIn } from '@/auth'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { Visibility, VisibilityOff } from '@mui/icons-material'; -import { signInEmailPassword } from '@/actions/auth.actions'; +import { signIn, useSession } from 'next-auth/react'; +import { authOptions } from '@/auth'; + +export function SingInForm() { + const session = useSession(); + console.log('Session: ', session); -export async function SingInForm() { const [showPassword, setShowPassword] = useState(false); + useEffect(() => { + if (session.data) { + toast.success('Login efetuado com sucesso!'); + setTimeout(() => {}, 1000); + window.location.href = '/'; + } + }, [session.data]); + const handleClickShowPassword = () => { setShowPassword(!showPassword); }; @@ -43,9 +52,10 @@ export async function SingInForm() { { - signInEmailPassword({ + signIn('credentials', { email: watch('email'), password: watch('password'), + redirect: false, }); }} className="grid gap-4 justify-center m-3" diff --git a/src/app/components/loginForm.tsx b/src/app/components/login.component.tsx similarity index 92% rename from src/app/components/loginForm.tsx rename to src/app/components/login.component.tsx index 3d44907..558c8f7 100644 --- a/src/app/components/loginForm.tsx +++ b/src/app/components/login.component.tsx @@ -6,7 +6,7 @@ import { GoogleAuthButton } from '@/app/components/buttons/googleAuth.button'; import { MicrosoftAuthButton } from '@/app/components/buttons/microsoftAuth.button'; import { AppleAuthButton } from '@/app/components/buttons/appleAuth.button'; -const LoginForm: React.FC = () => { +const LoginComponent: React.FC = () => { return ( <> @@ -33,4 +33,4 @@ const LoginForm: React.FC = () => { ); }; -export default LoginForm; +export default LoginComponent; diff --git a/src/app/components/AppBar.tsx b/src/app/components/navBar.component.tsx similarity index 79% rename from src/app/components/AppBar.tsx rename to src/app/components/navBar.component.tsx index 0ab8425..38bdd6a 100644 --- a/src/app/components/AppBar.tsx +++ b/src/app/components/navBar.component.tsx @@ -1,14 +1,15 @@ import React from 'react'; import { AppBar, Toolbar, IconButton, Typography, Box } from '@mui/material'; import MenuIcon from '@mui/icons-material/Menu'; -import Sidebar from './Sidebar'; +import Sidebar from './sidebar.component'; +import { SignOutButton } from './buttons/singOut.button'; -interface MyAppBarProps { +interface NavBarProps { handleDrawerOpen: () => void; open: boolean; } -const MyAppBar: React.FC = ({ handleDrawerOpen, open }) => { +const NavBar: React.FC = ({ handleDrawerOpen, open }) => { return ( <> @@ -29,6 +30,7 @@ const MyAppBar: React.FC = ({ handleDrawerOpen, open }) => { > Calculus + @@ -37,4 +39,4 @@ const MyAppBar: React.FC = ({ handleDrawerOpen, open }) => { ); }; -export default MyAppBar; +export default NavBar; diff --git a/src/app/components/Sidebar.tsx b/src/app/components/sidebar.component.tsx similarity index 82% rename from src/app/components/Sidebar.tsx rename to src/app/components/sidebar.component.tsx index 5000d80..64770ae 100644 --- a/src/app/components/Sidebar.tsx +++ b/src/app/components/sidebar.component.tsx @@ -1,10 +1,20 @@ +'use client'; + import Link from 'next/link'; import HomeIcon from '@mui/icons-material/Home'; import DashboardIcon from '@mui/icons-material/Dashboard'; import { Drawer, IconButton, Box } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; +import { useSession } from 'next-auth/react'; + +interface SideBarProps { + handleDrawerOpen: () => void; + open: boolean; +} + +const Sidebar : React.FC = ({ handleDrawerOpen, open }) => { + const session = useSession(); -const Sidebar = ({ open, handleDrawerOpen }) => { return ( @@ -24,7 +34,7 @@ const Sidebar = ({ open, handleDrawerOpen }) => {
  • Home diff --git a/src/app/home/page.tsx b/src/app/home/page.tsx new file mode 100644 index 0000000..59f7429 --- /dev/null +++ b/src/app/home/page.tsx @@ -0,0 +1,18 @@ +'use client'; + +import { useSession } from "next-auth/react"; +import { SignOutButton } from "../components/buttons/singOut.button"; + +export default function HomePage() { + const session = useSession(); + + console.log('my user: ' + session.data?.user) + return( +
    +

    {session.data?.user.name}

    +

    {session.data?.user.email}

    +

    Esta tela ainda está em desenvolvimento :)

    + +
    + ) +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 002769d..9cea972 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -5,7 +5,7 @@ import SessionProvider from '@/app/components/sessionProvider'; import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import './globals.css'; -import ClientLayout from './components/ClientLayout'; +import ClientLayout from './components/clientLayout'; const inter = Inter({ subsets: ['latin'] }); @@ -22,10 +22,12 @@ export default async function RootLayout({ return ( - - {children} + + {children} + + ); diff --git a/src/app/page.tsx b/src/app/page.tsx index 3ee534e..8d8e3f1 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,26 +4,18 @@ import React from 'react'; import Image from 'next/image'; import Link from 'next/link'; import roboProfessor from '../public/robo_professor.png'; -import { auth } from '@/auth'; -import { endSession } from '@/actions/auth.actions'; -import { Button } from '@mui/material'; +import { SignOutButton } from './components/buttons/singOut.button'; -export default async function LandingPage() { - const session = await auth(); - console.log('session home', session); - return session ? ( - <> -

    Logado

    - - - ) : ( +import { useSession } from 'next-auth/react'; + +export default function LandingPage() { + const session = useSession(); + + if(session.data) { + window.location.href = '/home'; + } + + return (

    Calculus

    diff --git a/src/auth.ts b/src/auth.ts index 72e0ef4..457bbde 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,14 +1,13 @@ -import NextAuth from 'next-auth'; -import type { NextAuthConfig } from 'next-auth'; +import { Awaitable, NextAuthOptions } from 'next-auth'; import CredentialsProvider from 'next-auth/providers/credentials'; import { loginWithEmailAndPassword } from '@/services/user.service'; import { privateRoutes } from '@/contains/constants'; -import Google from 'next-auth/providers/google'; +import GoogleProvider from 'next-auth/providers/google'; +import { JWT } from 'next-auth/jwt'; -export const config = { - trustHost: true, +export const authOptions: NextAuthOptions = { providers: [ - Google({ + GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, authorization: { @@ -37,8 +36,8 @@ export const config = { console.log('req', req); const res = await loginWithEmailAndPassword( - credentials.email as string, - credentials.password as string, + credentials!.email as string, + credentials!.password as string, ); if (res?.status !== 201) { throw new Error(res?.data.message); @@ -55,6 +54,7 @@ export const config = { }), ], secret: process.env.NEXTAUTH_SECRET, + callbacks: { async signIn({ account, profile }) { console.log( @@ -88,15 +88,13 @@ export const config = { ) { const { refreshToken, ...rest } = token; - return rest; + return rest as Awaitable; } return null; - // return await refreshAccessToken(token) }, async session({ session, token }) { console.log('session => ', session); - return { ...session, user: { @@ -141,7 +139,4 @@ export const config = { return true; }, }, - debug: process.env.NODE_ENV === 'development', -} satisfies NextAuthConfig; - -export const { handlers, signIn, signOut, auth } = NextAuth(config); +}; diff --git a/src/middleware.ts b/src/middleware.ts deleted file mode 100644 index 345d04d..0000000 --- a/src/middleware.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { auth as middleware } from '@/auth'; - -export const config = { - matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'], -}; diff --git a/src/services/user.service.ts b/src/services/user.service.ts index 5468615..3fed767 100644 --- a/src/services/user.service.ts +++ b/src/services/user.service.ts @@ -1,8 +1,5 @@ -import { NextResponse } from 'next/server'; import api from './api.service'; import { CalculusRequest } from '@/lib/interfaces/request.interface'; -import { User } from 'next-auth'; -import { signOut } from '@/auth'; export const createUser = async (data: any): Promise => { console.log(`Data: ${data}`); @@ -40,7 +37,3 @@ export const googleCallback = async () => { const response = await api.get('auth/google/callback'); return response; }; - -export const userSignOut = () => { - signOut(); -}; diff --git a/tsconfig.json b/tsconfig.json index e288596..b6a1c26 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,6 @@ ], "paths": { "@/*": ["./src/*"], - "auth": ["./src/auth"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/app/api/auth/[...nextauth]"], From 4f941a33cd5aaadf280678ad41ff6b740d2dd0ca Mon Sep 17 00:00:00 2001 From: Natanael Filho Date: Tue, 30 Jul 2024 01:19:07 -0300 Subject: [PATCH 2/4] Adding google autentication --- src/app/(auth)/login/page.tsx | 2 +- src/app/(auth)/oauth/page.tsx | 29 +++++++++++++++---- .../components/buttons/appleAuth.button.tsx | 2 +- .../components/buttons/googleAuth.button.tsx | 2 +- .../buttons/microsoftAuth.button.tsx | 2 +- src/app/components/buttons/singOut.button.tsx | 2 +- src/app/components/login.component.tsx | 4 +-- src/auth.ts | 18 ++++++++++++ 8 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index b46adc6..920eb19 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -5,7 +5,7 @@ import Image from 'next/image'; import calcuclusLogo from '@/public/calculus-logo.svg'; import LoginComponent from '@/app/components/login.component'; -export default async function LoginPage() { +export default function LoginPage() { return ( diff --git a/src/app/(auth)/oauth/page.tsx b/src/app/(auth)/oauth/page.tsx index 8ee699c..74da799 100644 --- a/src/app/(auth)/oauth/page.tsx +++ b/src/app/(auth)/oauth/page.tsx @@ -1,7 +1,26 @@ +'use client'; + +import { signIn, useSession } from "next-auth/react"; +import { useEffect, useState } from "react"; +import { useSearchParams } from 'next/navigation' + export default function OAuth() { - // useEffect(() => { - // if (accessToken) { - // signIn('google', { callbackUrl: '/your-redirect-url', accessToken }); - // } - // }, [accessToken]); + const session = useSession(); + const [authenticated, setAuthenticated] = useState(false); + const [message, setMessage] = useState("Carregando..."); + const searchParams = useSearchParams(); + const token = searchParams.get('token'); + + useEffect(() => { + if (token && !authenticated) { + signIn('credentials', {token}) + setMessage("Login efetuado com sucesso! redirecionando"); + setAuthenticated(true); + setTimeout(() => {}, 1000); + window.location.href = '/home'; + } + }, [token]); + return (<> +

    {message}

    + ); } diff --git a/src/app/components/buttons/appleAuth.button.tsx b/src/app/components/buttons/appleAuth.button.tsx index 024b342..a2f78b0 100644 --- a/src/app/components/buttons/appleAuth.button.tsx +++ b/src/app/components/buttons/appleAuth.button.tsx @@ -11,7 +11,7 @@ export function AppleAuthButton() { }; return ( -
    - ) -} \ No newline at end of file + console.log('my user: ' + session.data?.user); + return ( +
    +

    + {session.data?.user.name} +

    +

    + {session.data?.user.email} +

    +

    + Esta tela ainda está em desenvolvimento :) +

    + +
    + ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9cea972..4f4b941 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -23,9 +23,7 @@ export default async function RootLayout({ - - {children} - + {children} diff --git a/src/app/page.tsx b/src/app/page.tsx index 8d8e3f1..dd18678 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,14 +4,14 @@ import React from 'react'; import Image from 'next/image'; import Link from 'next/link'; import roboProfessor from '../public/robo_professor.png'; -import { SignOutButton } from './components/buttons/singOut.button'; +import { SignOutButton } from './components/buttons/signOut.button'; import { useSession } from 'next-auth/react'; export default function LandingPage() { const session = useSession(); - if(session.data) { + if (session.data) { window.location.href = '/home'; } diff --git a/src/contains/constants.ts b/src/contains/constants.ts index d597b9d..3309d58 100644 --- a/src/contains/constants.ts +++ b/src/contains/constants.ts @@ -1 +1 @@ -export const privateRoutes = ['/admin']; +export const privateRoutes = ['/admin', '/home']; diff --git a/src/lib/auth.actions.ts b/src/lib/auth.actions.ts new file mode 100644 index 0000000..42e3a93 --- /dev/null +++ b/src/lib/auth.actions.ts @@ -0,0 +1,7 @@ +'use server'; + +import { signIn } from 'next-auth/react'; + +export async function signInOAuth(token: string) { + await signIn('credentials', { token: token }); +} diff --git a/src/auth.ts b/src/lib/auth.ts similarity index 79% rename from src/auth.ts rename to src/lib/auth.ts index e6bce2b..a665495 100644 --- a/src/auth.ts +++ b/src/lib/auth.ts @@ -3,10 +3,24 @@ import CredentialsProvider from 'next-auth/providers/credentials'; import { loginWithEmailAndPassword } from '@/services/user.service'; import { privateRoutes } from '@/contains/constants'; import GoogleProvider from 'next-auth/providers/google'; +import AzureADProvider from 'next-auth/providers/azure-ad'; import { JWT } from 'next-auth/jwt'; export const authOptions: NextAuthOptions = { providers: [ + AzureADProvider({ + clientId: process.env.MICROSOFT_CLIENT_ID!, + clientSecret: process.env.MICROSOFT_CLIENT_SECRET!, + tenantId: process.env.MICROSOFT_TENANT_ID!, + authorization: { + params: { + prompt: 'consent', + access_type: 'offline', + response_type: 'code', + request_uri: `${process.env.NEXT_PUBLIC_API_URL!}/auth/microsoft/callback`, + }, + }, + }), GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, @@ -39,18 +53,18 @@ export const authOptions: NextAuthOptions = { console.log('credentials', credentials); console.log('req', req); if (credentials!.token) { - console.log("Eu nasci") - const token = credentials!.token; - const decodedAccessToken = JSON.parse( - Buffer.from(token!.split('.')[1], 'base64').toString(), - ); - const user = { - id: decodedAccessToken['id'], - name: decodedAccessToken['name'], - email: decodedAccessToken['email'], - accessToken: token, - } - return user + console.log('Eu nasci'); + const token = credentials!.token; + const decodedAccessToken = JSON.parse( + Buffer.from(token!.split('.')[1], 'base64').toString(), + ); + const user = { + id: decodedAccessToken['id'], + name: decodedAccessToken['name'], + email: decodedAccessToken['email'], + accessToken: token, + }; + return user; } const res = await loginWithEmailAndPassword( @@ -81,6 +95,9 @@ export const authOptions: NextAuthOptions = { if (account?.provider === 'google') { return `${process.env.NEXT_PUBLIC_API_URL}/auth/google/callback`; } + if (account?.provider === 'azure-ad') { + return `${process.env.NEXT_PUBLIC_API_URL}/auth/microsoft/callback`; + } return true; }, @@ -104,7 +121,7 @@ export const authOptions: NextAuthOptions = { token.accessTokenExpires && Date.now() < Number(token.accessTokenExpires) ) { - const { refreshToken, ...rest } = token; + const { ...rest } = token; return rest as Awaitable; } From ab6e371a7a52f2dd8da7a9425e5ab63f6ede6c1f Mon Sep 17 00:00:00 2001 From: Paulo Henrique Gontijo <44791309+paulohgontijoo@users.noreply.github.com> Date: Wed, 31 Jul 2024 00:49:03 +0000 Subject: [PATCH 4/4] =?UTF-8?q?[refact](#69):=20refatorando=20c=C3=B3digo?= =?UTF-8?q?=20para=20ajustar=20build=20do=20ambiente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 4 +-- package.json | 2 +- src/app/(auth)/oauth/page.tsx | 30 +++++++++++++-------- src/app/api/auth/[...nextauth]/route.ts | 2 +- src/lib/auth.ts | 36 ++----------------------- 5 files changed, 25 insertions(+), 49 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index da0465c..e32729a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,11 +4,11 @@ services: restart: on-failure build: . ports: - - "4000:4000" + - "3000:3000" environment: - NODE_ENV=development volumes: - ./src:/app/src env_file: - - .env.local + - .env \ No newline at end of file diff --git a/package.json b/package.json index 972ebbe..65cecaa 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dev": "next dev", "format": "prettier --write \"src/**/*.tsx\" \"src/**/*.ts\" \"test/**/*.ts\"", "build": "next build", - "start": "next start -p 4000", + "start": "next start -p 3000", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest --passWithNoTests --no-cache --runInBand", "test:all": "npm run test -- --coverage --config jest.config.ts" diff --git a/src/app/(auth)/oauth/page.tsx b/src/app/(auth)/oauth/page.tsx index fd48cd0..cd48612 100644 --- a/src/app/(auth)/oauth/page.tsx +++ b/src/app/(auth)/oauth/page.tsx @@ -1,12 +1,14 @@ +// page.tsx + 'use client'; import { signIn, useSession } from 'next-auth/react'; import { useEffect, useState } from 'react'; import { useSearchParams } from 'next/navigation'; -import { signInOAuth } from '@/lib/auth.actions'; +import { Suspense } from 'react'; -export default function OAuth() { - const session = useSession(); +const OAuthContent = () => { + const { data: session } = useSession(); const [authenticated, setAuthenticated] = useState(false); const [message, setMessage] = useState('Carregando...'); const searchParams = useSearchParams(); @@ -15,22 +17,28 @@ export default function OAuth() { useEffect(() => { if (token && !authenticated) { const signInWithToken = async () => { - await signIn('credentials', { token: token }); - if (session.data) { + await signIn('credentials', { token }); + if (session) { setAuthenticated(true); setMessage('Login efetuado com sucesso! redirecionando'); - await setTimeout(() => {}, 5000); + await new Promise((resolve) => setTimeout(resolve, 5000)); window.location.href = '/home'; } }; signInWithToken(); } - }, [session.data]); + }, [token, authenticated, session]); + + return

    {message}

    ; +}; +const OAuthPage = () => { return ( - <> -

    {message}

    - + Loading...}> + + ); -} +}; + +export default OAuthPage; diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index 18485bd..6499b53 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -1,5 +1,5 @@ import { authOptions } from '@/lib/auth'; -import NextAuth from 'next-auth/next'; +import NextAuth from "next-auth" const handler = NextAuth(authOptions); diff --git a/src/lib/auth.ts b/src/lib/auth.ts index a665495..a70a421 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -121,11 +121,9 @@ export const authOptions: NextAuthOptions = { token.accessTokenExpires && Date.now() < Number(token.accessTokenExpires) ) { - const { ...rest } = token; - - return rest as Awaitable; + return token as Awaitable; } - return null; + throw new Error('Token expired or invalid'); }, async session({ session, token }) { @@ -143,35 +141,5 @@ export const authOptions: NextAuthOptions = { error: token.error, }; }, - authorized({ request, auth }) { - const { pathname } = request.nextUrl; - - const searchTerm = request.nextUrl.pathname - .split('/') - .slice(0, 2) - .join('/'); - - if (privateRoutes.includes(searchTerm)) { - console.log( - `${!!auth ? 'Can' : 'Cannot'} access private route ${searchTerm}`, - ); - return !!auth; - // if the pathname starts with one of the routes below and the user is already logged in, forward the user to the home page - } else if ( - pathname.startsWith('/login') || - pathname.startsWith('/forgot-password') || - pathname.startsWith('/register') - ) { - const isLoggedIn = !!auth; - - if (isLoggedIn) { - return Response.redirect(new URL('/', request.nextUrl)); - } - - return true; - } - - return true; - }, }, };