# Reading "Getting Started with NextAuth.js"
These are my comments when reading the Getting Started (opens new window) guide of NextAuth.js for a Nextra lab.
# Repo https://github.com/nextauthjs/next-auth-example/
In New Project (opens new window) the guide suggests to clone the repo https://next-auth-example.vercel.app/ (opens new window) and learn from it, so I cloned it.
In the main
branch the version of next-auth
is beta
and
next
is latest
. The example used the app
folder instead of pages
.
The version of next
installed at this time (November 2024) was:
I noticed the next-auth has no public documentation for the beta
version.
There are 5 branches. The others 4 are stale
. 2 test/*
branches, one feat/*
branch and one apple-sign-in
branch using next
12. All of them can be used to learn.
Conclusion
Discarded the idea of using it as the main learning resource.
So, I follow with the section Existing Project (opens new window) path.
# Initial Steps
I started fron the nextra assignment for the fake student https://github.com/ULL-MII-SYTWS-2425/nextra-casiano-rodriguez-leon-alu0100291865 (opens new window).
Made a new branch guide
from commit
526ce78 (opens new window)
when I was on main
: https://github.com/ULL-MII-SYTWS-2425/nextra-casiano-rodriguez-leon-alu0100291865/tree/guide (opens new window)
Added the API route pages/api/auth/[...nextauth].js
as explained at https://next-auth.js.org/getting-started/example#add-api-route (opens new window). See https://github.com/ULL-MII-SYTWS-2425/nextra-casiano-rodriguez-leon-alu0100291865/blob/guide/pages/api/auth/[...nextauth].js (opens new window)
Bug
I forced the script "dev": "next -p 3000",
to listen in port 3000 in the package.json
, since I have found a bug in next-auth GitHub provider. The sigin
page seems to have hardcoded the port to 3000 http://localhost:3000/api/auth/signin/github
: https://github.com/ULL-MII-SYTWS-2425/nextra-casiano-rodriguez-leon-alu0100291865/blob/guide/package.json#L6-L10 (opens new window)
# Add API route
When reading the section [Add API route](Add API route) for Nextra I've got errors that were fixed
by changing the calls to GithubProvider
and NextAuth
by adding .default
:
File pages/api/auth/[...nextauth].js
import NextAuth from "next-auth" // https://next-auth.js.org/getting-started/example#add-api-route
import GithubProvider from "next-auth/providers/github"
export const authOptions = {
// Configure one or more authentication providers
providers: [
GithubProvider.default({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
// ...add more providers here
]
}
export default NextAuth.default(authOptions)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
For an explanation of how Next.js API routes work see https://ull-pl.vercel.app/nextra-playground/authorization/next-auth-tutorial#creating-the-server-config (opens new window) at my PL Notes.
Behind the scenes, this code creates all the relevant OAuth API routes
within /api/auth/*
so that auth API requests can be handled by NextAuth.js.
In this way, NextAuth.js stays in charge of the whole application's request/response flow.
See https://ull-pl.vercel.app/nextra-playground/authorization/next-auth-tutorial#routes (opens new window)
# SessionProvider component in pages/_app.jsx
I also changed the main file pages/_app.jsx
to use the SessionProvider
as explained at
https://next-auth.js.org/getting-started/example#configure-shared-session-state (opens new window)
File pages/_app.jsx
:
/* Old code
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}
*/
import { SessionProvider } from "next-auth/react"
export default function App({
Component,
pageProps: { session, ...pageProps },
}) {
return (
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# login-btn component
Added the login-btn
component as explained at
https://next-auth.js.org/getting-started/example#frontend---add-react-hook (opens new window)
import { useSession, signIn, signOut } from "next-auth/react"
export default function Component() {
const { data: session, status: status } = useSession()
if (status === "loading") {
return <p>Loading...</p>
}
if (session) {
return (
<>
Signed in as {session.user.email} <br />
<button onClick={() => signOut()}>Sign out</button>
</>
)
}
return (
<>
Not signed in <br />
<button onClick={() => signIn()}>Sign in</button>
</>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# useSession() NextAuth React Hook
The useSession() (opens new window) React Hook in the NextAuth.js client is the easiest way to check if someone is signed in.
useSession()
returns an object containing two values: data
and status
:
data: This can be three values: Session
/ undefined
/ null
.
- when the session hasn't been fetched yet,
data
will beundefined
- in case it failed to retrieve the session,
data
will benull
- in case of success,
data
will be aSession
object.
status: Is a enum mapping to three possible session states: "loading" | "authenticated" | "unauthenticated"
To wrap all the pages, make sure that <SessionProvider>
is added to pages/_app.js
.
# signIn() method
Using the client side signIn() (opens new window) method ensures the user ends back on the page they started on after completing a sign in flow. It will also handle CSRF Tokens for you automatically when signing in with email.
By default, when calling the signIn()
method with no arguments, you will be redirected to the NextAuth.js sign-in page. If you want to skip that and get redirected to your provider's page immediately, call the signIn() method with the provider's id.
For example to sign in with GitHub:
import { signIn } from "next-auth/react"
export default () => (
<button onClick={() => signIn("github")}>Sign in with GitHub</button>
)
2
3
4
5
The signIn()
method receives a second argument, an object with options.
The most common options are callbackUrl (opens new window)
and redirect (opens new window).
The callbackUrl specifies to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from.
Examples:
signIn(undefined, { callbackUrl: '/foo' }) // A relative url starting with a slash
signIn('google', { callbackUrl: 'http://localhost:3000/bar' }) // Or an absolute URL at the same host name,
signIn('email', { email, callbackUrl: 'http://localhost:3000/foo' })
signIn('credentials', { redirect: false, password: 'password' }) // Disable the redirect and handle the error on the same page.
signIn('email', { redirect: false, email: 'bill@fillmurray.com' }) // In such case signIn will return a Promise,
2
3
4
5
If redirect
is set to false
, the signIn
method will return a Promise that resolves to
an object with the following properties:
{
error: string | undefined // Error message if there was an error
status: number // HTTP status code
ok: boolean // `true` if the request was successful, `false` otherwise
url: string | null // The URL the user should be redirected to or null `null` if there was an error
}
2
3
4
5
6