Skip to content

Commit 038e31f

Browse files
authored
Merge pull request #12 from PupSpot/adding_auth0
😄 Adding auth0 login to frontend
2 parents de03792 + c04c6e2 commit 038e31f

File tree

14 files changed

+6693
-563
lines changed

14 files changed

+6693
-563
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
/.pnp
66
.pnp.js
77
.yarn/install-state.gz
8+
package-lock.json/
9+
package.json/
810

911
# testing
1012
/coverage

app/api/auth/[...auth0].ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { handleAuth, handleLogout } from '@auth0/nextjs-auth0';
2+
import type { NextApiRequest, NextApiResponse } from 'next';
3+
4+
export default handleAuth({
5+
logout: async (req: NextApiRequest, res: NextApiResponse) => {
6+
try {
7+
await handleLogout(req, res, {
8+
returnTo: process.env.AUTH0_BASE_URL,
9+
logoutParams: {
10+
federated: 'true'
11+
}
12+
});
13+
} catch (error) {
14+
console.error('Error during logout:', error);
15+
res.status(500).end('Internal Server Error');
16+
}
17+
},
18+
});

app/components/LoginButton.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const handleLogin = () => {
2+
// Clear any existing auth tokens/cookies
3+
document.cookie.split(";").forEach((c) => {
4+
document.cookie = c
5+
.replace(/^ +/, "")
6+
.replace(/=.*/, "=;expires=" + new Date().toUTCString() + ";path=/");
7+
});
8+
9+
window.location.href = '/api/auth/login';
10+
};

app/layout.tsx

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import type { Metadata } from "next";
2+
import { UserProvider } from '@auth0/nextjs-auth0/client';
23
import localFont from "next/font/local";
34
import "./globals.css";
4-
import React from "react";
5+
import { Providers } from './providers';
56

67
const geistSans = localFont({
78
src: "./fonts/GeistVF.woff",
89
variable: "--font-geist-sans",
910
weight: "100 900",
1011
});
12+
1113
const geistMono = localFont({
1214
src: "./fonts/GeistMonoVF.woff",
1315
variable: "--font-geist-mono",
@@ -45,19 +47,14 @@ export const metadata: Metadata = {
4547

4648
export default function RootLayout({
4749
children,
48-
}: Readonly<{
49-
children: React.ReactNode;
50-
}>) {
50+
}: {
51+
children: React.ReactNode
52+
}) {
5153
return (
52-
<html lang="en">
53-
<head>
54-
<link rel="icon" href="/pawicon.png" type="image/icon" />
55-
</head>
56-
<body
57-
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
58-
>
59-
{children}
54+
<html lang="en" suppressHydrationWarning>
55+
<body>
56+
<Providers>{children}</Providers>
6057
</body>
6158
</html>
6259
);
63-
}
60+
}

app/providers.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use client';
2+
3+
import { UserProvider } from '@auth0/nextjs-auth0/client';
4+
5+
export function Providers({ children }: { children: React.ReactNode }) {
6+
return (
7+
<UserProvider>
8+
{children}
9+
</UserProvider>
10+
);
11+
}

app/utils/auth0-config.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { initAuth0 } from '@auth0/nextjs-auth0';
2+
3+
export const auth0 = initAuth0({
4+
baseURL: process.env.AUTH0_BASE_URL,
5+
clientID: process.env.AUTH0_CLIENT_ID,
6+
clientSecret: process.env.AUTH0_CLIENT_SECRET,
7+
issuerBaseURL: process.env.AUTH0_ISSUER_BASE_URL,
8+
secret: process.env.AUTH0_SECRET,
9+
session: {
10+
absoluteDuration: 24 * 60 * 60,
11+
cookie: {
12+
secure: process.env.NODE_ENV === "production",
13+
sameSite: "lax",
14+
domain: process.env.NODE_ENV === "production" ? "your-domain.com" : "localhost",
15+
}
16+
},
17+
});

components/BrowserComponent.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use client';
2+
3+
import { useEffect, useState } from 'react';
4+
5+
export function BrowserComponent() {
6+
const [mounted, setMounted] = useState(false);
7+
8+
useEffect(() => {
9+
setMounted(true);
10+
}, []);
11+
12+
if (!mounted) {
13+
return null; // or loading state
14+
}
15+
16+
return (
17+
<div>
18+
{/* Your component content goes here */}
19+
</div>
20+
);
21+
}

components/ErrorBoundry.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// components/ErrorBoundary.tsx
2+
'use client';
3+
4+
import { Component, ErrorInfo, ReactNode } from 'react';
5+
6+
interface Props {
7+
children: ReactNode;
8+
}
9+
10+
interface State {
11+
hasError: boolean;
12+
}
13+
14+
export class ErrorBoundary extends Component<Props, State> {
15+
public state: State = {
16+
hasError: false
17+
};
18+
19+
public static getDerivedStateFromError(_: Error): State {
20+
return { hasError: true };
21+
}
22+
23+
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
24+
console.error('Uncaught error:', error, errorInfo);
25+
}
26+
27+
public render() {
28+
if (this.state.hasError) {
29+
return (
30+
<div className="flex items-center justify-center min-h-screen">
31+
<div className="text-center">
32+
<h2 className="text-2xl font-bold mb-4">Something went wrong</h2>
33+
<button
34+
className="bg-blue-600 text-white px-4 py-2 rounded"
35+
onClick={() => this.setState({ hasError: false })}
36+
>
37+
Try again
38+
</button>
39+
</div>
40+
</div>
41+
);
42+
}
43+
44+
return this.props.children;
45+
}
46+
}

0 commit comments

Comments
 (0)