Skip to content

Commit bb1f576

Browse files
Next: Authentication with next-auth
1 parent 57d5531 commit bb1f576

28 files changed

+8690
-0
lines changed

Nextjs/nextjs-auth/.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# next.js
12+
/.next/
13+
/out/
14+
15+
# production
16+
/build
17+
18+
# misc
19+
.DS_Store
20+
*.pem
21+
22+
# debug
23+
npm-debug.log*
24+
yarn-debug.log*
25+
yarn-error.log*
26+
27+
# local env files
28+
.env.local
29+
.env.development.local
30+
.env.test.local
31+
.env.production.local
32+
33+
# vercel
34+
.vercel

Nextjs/nextjs-auth/.vscode/settings.json

Whitespace-only changes.

Nextjs/nextjs-auth/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2+
3+
## Getting Started
4+
5+
First, run the development server:
6+
7+
```bash
8+
npm run dev
9+
# or
10+
yarn dev
11+
```
12+
13+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
14+
15+
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
16+
17+
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
18+
19+
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
20+
21+
## Learn More
22+
23+
To learn more about Next.js, take a look at the following resources:
24+
25+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
26+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
27+
28+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
29+
30+
## Deploy on Vercel
31+
32+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
33+
34+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { useState, useRef } from "react";
2+
import { signIn } from "next-auth/client";
3+
import classes from "./auth-form.module.css";
4+
import { useRouter } from "next/router";
5+
6+
const createUser = async (email, password) => {
7+
const response = await fetch("/api/auth/signup", {
8+
method: "POST",
9+
body: JSON.stringify({ email, password }),
10+
headers: {
11+
"Content-Type": "application/json",
12+
},
13+
});
14+
15+
const data = await response.json();
16+
17+
if (!response.ok) {
18+
throw new Error(data.message || "Something went wrong!");
19+
}
20+
21+
return data;
22+
};
23+
24+
function AuthForm() {
25+
const router = useRouter();
26+
const [isLogin, setIsLogin] = useState(true);
27+
28+
const emailRef = useRef();
29+
const passwordRef = useRef();
30+
31+
function switchAuthModeHandler() {
32+
setIsLogin((prevState) => !prevState);
33+
}
34+
35+
const handleSubmit = async (event) => {
36+
event.preventDefault();
37+
38+
const enteredEmail = emailRef.current.value;
39+
const enteredPassword = passwordRef.current.value;
40+
41+
if (isLogin) {
42+
const result = await signIn("credentials", {
43+
redirect: false,
44+
email: enteredEmail,
45+
password: enteredPassword,
46+
});
47+
48+
if (result.error) {
49+
console.error(result.error);
50+
return;
51+
}
52+
53+
console.log(result);
54+
55+
if (result.ok) {
56+
router.replace("/profile");
57+
}
58+
} else {
59+
try {
60+
const result = await createUser(enteredEmail, enteredPassword);
61+
} catch (err) {
62+
console.error(err);
63+
}
64+
}
65+
};
66+
67+
return (
68+
<section className={classes.auth}>
69+
<h1>{isLogin ? "Login" : "Sign Up"}</h1>
70+
<form onSubmit={handleSubmit}>
71+
<div className={classes.control}>
72+
<label htmlFor="email">Your Email</label>
73+
<input type="email" id="email" ref={emailRef} required />
74+
</div>
75+
<div className={classes.control}>
76+
<label htmlFor="password">Your Password</label>
77+
<input type="password" id="password" ref={passwordRef} required />
78+
</div>
79+
<div className={classes.actions}>
80+
<button>{isLogin ? "Login" : "Create Account"}</button>
81+
<button
82+
type="button"
83+
className={classes.toggle}
84+
onClick={switchAuthModeHandler}
85+
>
86+
{isLogin ? "Create new account" : "Login with existing account"}
87+
</button>
88+
</div>
89+
</form>
90+
</section>
91+
);
92+
}
93+
94+
export default AuthForm;
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
.auth {
2+
margin: 3rem auto;
3+
width: 95%;
4+
max-width: 25rem;
5+
border-radius: 6px;
6+
background-color: #38015c;
7+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
8+
padding: 1rem;
9+
text-align: center;
10+
}
11+
12+
.auth h1 {
13+
text-align: center;
14+
color: white;
15+
}
16+
17+
.control {
18+
margin-bottom: 0.5rem;
19+
}
20+
21+
.control label {
22+
display: block;
23+
color: white;
24+
font-weight: bold;
25+
margin-bottom: 0.5rem;
26+
}
27+
28+
.control input {
29+
font: inherit;
30+
background-color: #f1e1fc;
31+
color: #38015c;
32+
border-radius: 4px;
33+
border: 1px solid white;
34+
width: 100%;
35+
text-align: left;
36+
padding: 0.25rem;
37+
}
38+
39+
.actions {
40+
margin-top: 1.5rem;
41+
display: flex;
42+
flex-direction: column;
43+
align-items: center;
44+
}
45+
46+
.actions button {
47+
cursor: pointer;
48+
font: inherit;
49+
color: white;
50+
background-color: #9f5ccc;
51+
border: 1px solid #9f5ccc;
52+
border-radius: 4px;
53+
padding: 0.5rem 2.5rem;
54+
}
55+
56+
.actions button:hover {
57+
background-color: #873abb;
58+
border-color: #873abb;
59+
}
60+
61+
.actions .toggle {
62+
margin-top: 1rem;
63+
background-color: transparent;
64+
color: #9f5ccc;
65+
border: none;
66+
padding: 0.15rem 1.5rem;
67+
}
68+
69+
.actions .toggle:hover {
70+
background-color: transparent;
71+
color: #ae82cc;
72+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Fragment } from 'react';
2+
3+
import MainNavigation from './main-navigation';
4+
5+
function Layout(props) {
6+
return (
7+
<Fragment>
8+
<MainNavigation />
9+
<main>{props.children}</main>
10+
</Fragment>
11+
);
12+
}
13+
14+
export default Layout;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import Link from "next/link";
2+
import { useSession, signOut } from "next-auth/client";
3+
4+
import classes from "./main-navigation.module.css";
5+
import { Fragment } from "react";
6+
7+
function MainNavigation() {
8+
const [session, loading] = useSession();
9+
10+
const handleLogout = async () => {
11+
signOut();
12+
};
13+
14+
return (
15+
<header className={classes.header}>
16+
<Link href="/">
17+
<a>
18+
<div className={classes.logo}>Next Auth</div>
19+
</a>
20+
</Link>
21+
<nav>
22+
<ul>
23+
{!session && !loading && (
24+
<li>
25+
<Link href="/auth">Login</Link>
26+
</li>
27+
)}
28+
{session && (
29+
<Fragment>
30+
<li>
31+
<Link href="/profile">Profile</Link>
32+
</li>
33+
<li>
34+
<button onClick={handleLogout}>Logout</button>
35+
</li>
36+
</Fragment>
37+
)}
38+
</ul>
39+
</nav>
40+
</header>
41+
);
42+
}
43+
44+
export default MainNavigation;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
.header {
2+
width: 100%;
3+
height: 5rem;
4+
background-color: #38015c;
5+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
6+
display: flex;
7+
justify-content: space-between;
8+
align-items: center;
9+
padding: 0 10%;
10+
}
11+
12+
.logo {
13+
font-family: 'Lato', sans-serif;
14+
font-size: 2rem;
15+
color: white;
16+
margin: 0;
17+
}
18+
19+
.header ul {
20+
list-style: none;
21+
margin: 0;
22+
padding: 0;
23+
display: flex;
24+
align-items: baseline;
25+
}
26+
27+
.header li {
28+
margin: 0 1rem;
29+
}
30+
31+
.header a {
32+
text-decoration: none;
33+
color: white;
34+
font-weight: bold;
35+
}
36+
37+
.header button {
38+
font: inherit;
39+
background-color: transparent;
40+
border: 1px solid white;
41+
color: white;
42+
font-weight: bold;
43+
padding: 0.5rem 1.5rem;
44+
border-radius: 6px;
45+
cursor: pointer;
46+
}
47+
48+
.header a:hover {
49+
color: #c291e2;
50+
}
51+
52+
.header button:hover {
53+
background-color: #c291e2;
54+
color: #38015c;
55+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { useRef } from "react";
2+
import classes from "./profile-form.module.css";
3+
4+
function ProfileForm(props) {
5+
const newPasswordRef = useRef();
6+
const oldPasswordRef = useRef();
7+
8+
const handleSubmit = (event) => {
9+
event.preventDefault();
10+
11+
const newPassword = newPasswordRef.current.value;
12+
const oldPassword = oldPasswordRef.current.value;
13+
14+
props.onPasswordChanged({
15+
oldPassword,
16+
newPassword,
17+
});
18+
};
19+
20+
return (
21+
<form className={classes.form} onSubmit={handleSubmit}>
22+
<div className={classes.control}>
23+
<label htmlFor="new-password">New Password</label>
24+
<input type="password" id="new-password" ref={newPasswordRef} />
25+
</div>
26+
<div className={classes.control}>
27+
<label htmlFor="old-password">Old Password</label>
28+
<input type="password" id="old-password" ref={oldPasswordRef} />
29+
</div>
30+
<div className={classes.action}>
31+
<button>Change Password</button>
32+
</div>
33+
</form>
34+
);
35+
}
36+
37+
export default ProfileForm;

0 commit comments

Comments
 (0)