From eb7332caa1a292430019e7ef58f12891228d153d Mon Sep 17 00:00:00 2001 From: Tushar Pandey Date: Tue, 25 Mar 2025 15:00:46 +0530 Subject: [PATCH 01/10] new sample app running state, tests failing --- Sample-01/.env.local.example | 10 +- Sample-01/app/api/auth/[auth0]/route.js | 3 - Sample-01/app/api/shows/route.js | 22 +- Sample-01/app/csr/page.jsx | 47 +- Sample-01/app/external/page.jsx | 16 +- Sample-01/app/layout.jsx | 7 +- Sample-01/app/profile/page.jsx | 62 +- Sample-01/app/ssr/page.jsx | 61 +- Sample-01/components/NavBar.jsx | 10 +- Sample-01/hooks/useAuthGuard.tsx | 51 + Sample-01/lib/auth0.ts | 15 + Sample-01/middleware.ts | 19 + Sample-01/package-lock.json | 9161 +++++++++++------------ Sample-01/package.json | 49 +- Sample-01/tests/app/csr.test.jsx | 6 +- Sample-01/tests/app/external.test.jsx | 6 +- Sample-01/tests/fixtures.jsx | 6 +- 17 files changed, 4560 insertions(+), 4991 deletions(-) delete mode 100644 Sample-01/app/api/auth/[auth0]/route.js create mode 100644 Sample-01/hooks/useAuthGuard.tsx create mode 100644 Sample-01/lib/auth0.ts create mode 100644 Sample-01/middleware.ts diff --git a/Sample-01/.env.local.example b/Sample-01/.env.local.example index 4ad54e3..5dd3169 100644 --- a/Sample-01/.env.local.example +++ b/Sample-01/.env.local.example @@ -1,7 +1,5 @@ AUTH0_SECRET=replace-with-your-own-secret-generated-with-openssl -AUTH0_BASE_URL=http://localhost:3000 -AUTH0_ISSUER_BASE_URL='https://{DOMAIN}' -AUTH0_CLIENT_ID='{CLIENT_ID}' -AUTH0_CLIENT_SECRET='{CLIENT_SECRET}' -AUTH0_AUDIENCE= -AUTH0_SCOPE='openid profile' +AUTH0_CLIENT_ID={CLIENT_ID} +AUTH0_CLIENT_SECRET={CLIENT_SECRET} +AUTH0_DOMAIN={DOMAIN} +APP_BASE_URL=http://localhost:3000 \ No newline at end of file diff --git a/Sample-01/app/api/auth/[auth0]/route.js b/Sample-01/app/api/auth/[auth0]/route.js deleted file mode 100644 index 1d2e4e4..0000000 --- a/Sample-01/app/api/auth/[auth0]/route.js +++ /dev/null @@ -1,3 +0,0 @@ -import { handleAuth } from '@auth0/nextjs-auth0'; - -export const GET = handleAuth(); diff --git a/Sample-01/app/api/shows/route.js b/Sample-01/app/api/shows/route.js index 6fe9042..0aa8290 100644 --- a/Sample-01/app/api/shows/route.js +++ b/Sample-01/app/api/shows/route.js @@ -1,12 +1,17 @@ -import { getAccessToken, withApiAuthRequired } from '@auth0/nextjs-auth0'; +import { auth0 } from '../../../lib/auth0'; import { NextResponse } from 'next/server'; -export const GET = withApiAuthRequired(async function shows(req) { +export async function GET(req) { + // Check if user is authenticated + const session = await auth0.getSession(); + if (!session) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); + } + try { - const res = new NextResponse(); - const { accessToken } = await getAccessToken(req, res, { - scopes: ['read:shows'] - }); + // Get access token + const { accessToken } = await auth0.getAccessToken(); + const apiPort = process.env.API_PORT || 3001; const response = await fetch(`http://localhost:${apiPort}/api/shows`, { headers: { @@ -15,8 +20,9 @@ export const GET = withApiAuthRequired(async function shows(req) { }); const shows = await response.json(); - return NextResponse.json(shows, res); + return NextResponse.json(shows); } catch (error) { + console.error('Auth0 or API error:', error); return NextResponse.json({ error: error.message }, { status: error.status || 500 }); } -}); +} diff --git a/Sample-01/app/csr/page.jsx b/Sample-01/app/csr/page.jsx index 9e232d2..bf8632b 100644 --- a/Sample-01/app/csr/page.jsx +++ b/Sample-01/app/csr/page.jsx @@ -1,29 +1,32 @@ 'use client'; import React from 'react'; -import { withPageAuthRequired } from '@auth0/nextjs-auth0/client'; +import useAuthGuard from '../../hooks/useAuthGuard'; + +export default function CSRPage() { + const { isAuthenticated, guardComponent } = useAuthGuard(); + + // If not authenticated or loading, show guard component + if (!isAuthenticated) return guardComponent; -export default withPageAuthRequired(function CSRPage() { return ( - <> -
-

Client-side Rendered Page

-
-

- You can protect a client-side rendered page by wrapping it with withPageAuthRequired. Only - logged in users will be able to access it. If the user is logged out, they will be redirected to the login - page instead. -

-

- Use the useUser hook to access the user profile from protected client-side rendered pages. The{' '} - useUser hook relies on the UserProvider Context Provider, so you need to wrap your - custom App Component with it. -

-

- You can also fetch the user profile by calling the /api/auth/me API route. -

-
+
+

Client-side Rendered Page

+
+

+ You can protect a client-side rendered page by wrapping it with withPageAuthRequired. Only + logged in users will be able to access it. If the user is logged out, they will be redirected to the login + page instead. +

+

+ Use the useUser hook to access the user profile from protected client-side rendered pages. The{' '} + useUser hook relies on the UserProvider Context Provider, so you need to wrap your + custom App Component with it. +

+

+ You can also fetch the user profile by calling the /auth/me API route. +

- +
); -}); +} diff --git a/Sample-01/app/external/page.jsx b/Sample-01/app/external/page.jsx index 5b7316c..40784dc 100644 --- a/Sample-01/app/external/page.jsx +++ b/Sample-01/app/external/page.jsx @@ -2,15 +2,18 @@ import React, { useState } from 'react'; import { Button } from 'reactstrap'; -import { withPageAuthRequired } from '@auth0/nextjs-auth0/client'; - +import useAuthGuard from '../../hooks/useAuthGuard'; +import Highlight from '../../components/Highlight'; import Loading from '../../components/Loading'; import ErrorMessage from '../../components/ErrorMessage'; -import Highlight from '../../components/Highlight'; -function External() { +export default function External() { + const { isAuthenticated, user, guardComponent } = useAuthGuard(); const [state, setState] = useState({ isLoading: false, response: undefined, error: undefined }); + // If not authenticated or loading, show guard component + if (!isAuthenticated) return guardComponent; + const callApi = async () => { setState(previous => ({ ...previous, isLoading: true })); @@ -68,8 +71,3 @@ function External() { ); } - -export default withPageAuthRequired(External, { - onRedirecting: () => , - onError: error => {error.message} -}); diff --git a/Sample-01/app/layout.jsx b/Sample-01/app/layout.jsx index 5fe40a8..50f9ed5 100644 --- a/Sample-01/app/layout.jsx +++ b/Sample-01/app/layout.jsx @@ -5,7 +5,10 @@ import NavBar from '../components/NavBar'; import { Container } from 'reactstrap'; import Footer from '../components/Footer'; import React from 'react'; -import { UserProvider } from '@auth0/nextjs-auth0/client'; +import initFontAwesome from '../utils/initFontAwesome'; + +// Initialize FontAwesome icons +initFontAwesome(); export default function RootLayout({ children }) { return ( @@ -20,13 +23,11 @@ export default function RootLayout({ children }) { -
{children}
-
); diff --git a/Sample-01/app/profile/page.jsx b/Sample-01/app/profile/page.jsx index 3286ba0..8279dff 100644 --- a/Sample-01/app/profile/page.jsx +++ b/Sample-01/app/profile/page.jsx @@ -2,47 +2,37 @@ import React from 'react'; import { Row, Col } from 'reactstrap'; -import { useUser, withPageAuthRequired } from '@auth0/nextjs-auth0/client'; - -import Loading from '../../components/Loading'; -import ErrorMessage from '../../components/ErrorMessage'; +import useAuthGuard from '../../hooks/useAuthGuard'; import Highlight from '../../components/Highlight'; -function Profile() { - const { user, isLoading } = useUser(); +export default function Profile() { + const { isAuthenticated, user, guardComponent } = useAuthGuard(); + + // If not authenticated or loading, show guard component + if (!isAuthenticated) return guardComponent; return ( <> - {isLoading && } - {user && ( - <> - - - Profile - - -

{user.name}

-

- {user.email} -

- -
- - {JSON.stringify(user, null, 2)} - - - )} + + + Profile + + +

{user.name}

+

+ {user.email} +

+ +
+ + {JSON.stringify(user, null, 2)} + ); } - -export default withPageAuthRequired(Profile, { - onRedirecting: () => , - onError: error => {error.message} -}); diff --git a/Sample-01/app/ssr/page.jsx b/Sample-01/app/ssr/page.jsx index c29a65e..7700659 100644 --- a/Sample-01/app/ssr/page.jsx +++ b/Sample-01/app/ssr/page.jsx @@ -1,31 +1,40 @@ import React from 'react'; -import { getSession, withPageAuthRequired } from '@auth0/nextjs-auth0'; - +import { auth0 } from '../../lib/auth0'; import Highlight from '../../components/Highlight'; -export default withPageAuthRequired( - async function SSRPage() { - const { user } = await getSession(); - return ( - <> -
-

Server-side Rendered Page

-
-

- You can protect a server-side rendered page by wrapping it with withPageAuthRequired. Only - logged in users will be able to access it. If the user is logged out, they will be redirected to the login - page instead.{' '} -

-
+export default async function SSRPage() { + const session = await auth0.getSession(); + + // Redirect to login if not authenticated + if (!session) { + return { + redirect: { + destination: '/auth/login', + permanent: false, + }, + }; + } + + const { user } = session; + + return ( + <> +
+

Server-side Rendered Page

+
+

+ You can protect a server-side rendered page by checking the session. Only + logged in users will be able to access it. If the user is logged out, they will be redirected to the login + page instead.{' '} +

-
-
-
User
- {JSON.stringify(user, null, 2)} -
+
+
+
+
User
+ {JSON.stringify(user, null, 2)}
- - ); - }, - { returnTo: '/ssr' } -); +
+ + ); +} diff --git a/Sample-01/components/NavBar.jsx b/Sample-01/components/NavBar.jsx index bf4eea4..369049f 100644 --- a/Sample-01/components/NavBar.jsx +++ b/Sample-01/components/NavBar.jsx @@ -14,7 +14,7 @@ import { DropdownMenu, DropdownItem } from 'reactstrap'; -import { useUser } from '@auth0/nextjs-auth0/client'; +import { useUser } from '@auth0/nextjs-auth0'; import PageLink from './PageLink'; import AnchorLink from './AnchorLink'; @@ -61,7 +61,7 @@ const NavBar = () => { {!isLoading && !user && ( @@ -92,7 +92,7 @@ const NavBar = () => { - + Log out @@ -103,7 +103,7 @@ const NavBar = () => { {!isLoading && !user && (