Skip to content

Instantly share code, notes, and snippets.

@thevisioner
Created March 7, 2023 18:42
Show Gist options
  • Save thevisioner/91ea39fd1de1a99ea729fea8f7edabab to your computer and use it in GitHub Desktop.
Save thevisioner/91ea39fd1de1a99ea729fea8f7edabab to your computer and use it in GitHub Desktop.
User Authentication in Next.js with Auth.js and Strapi
GOOGLE_OAUTH_CLIENT_ID=
GOOGLE_OAUTH_CLIENT_SECRET=
NEXTAUTH_SECRET=
# Use 127.0.0.1 instead of localhost to avoid issues with NextAuth.js
NEXTAUTH_URL=http://127.0.0.1:3000
STRAPI_BACKEND_URL=http://127.0.0.1:1337
// pages/api/auth/[...nextauth].ts
import { NextApiRequest, NextApiResponse } from "next";
import NextAuth, { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
export const authOptions: NextAuthOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_OAUTH_CLIENT_ID!,
clientSecret: process.env.GOOGLE_OAUTH_CLIENT_SECRET!,
}),
],
callbacks: {
// This method is not invoked when you persist sessions in a database.
async jwt({ token, account }) {
if (account) {
const res = await fetch(
`${process.env.STRAPI_BACKEND_URL}/api/auth/${account.provider}/callback?access_token=${account.access_token}`
);
const data = await res.json();
const { jwt, user } = data;
token.accessToken = jwt;
token.userId = user.id;
}
return token;
},
async session({ session, token, user }) {
// Send properties to the client, like an access_token from a provider.
session.user.accessToken = token.accessToken as string;
session.user.userId = token.userId as number;
return session;
},
},
session: {
// The default is `"jwt"`, an encrypted JWT (JWE) stored in the session cookie.
// If you use an `adapter` however, we default it to `"database"` instead.
// You can still force a JWT session by explicitly defining `"jwt"`.
strategy: "jwt",
},
// Not providing any secret or NEXTAUTH_SECRET will throw an error in production.
secret: process.env.NEXTAUTH_SECRET,
};
const auth = (req: NextApiRequest, res: NextApiResponse) =>
NextAuth(req, res, authOptions);
export default auth;
// pages/_app.tsx
import type { AppProps } from "next/app";
import { SessionProvider } from "next-auth/react";
export default function App({
Component,
pageProps: { session, ...pageProps },
}: AppProps) {
return (
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
);
}
// pages/index.tsx
import { useSession, signIn, signOut } from "next-auth/react";
export default function IndexPage() {
const { data: session, status } = useSession();
const isLoading = status === "loading";
if (isLoading) return "Loading...";
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>
</>
);
}
// types/next-auth.d.ts
import NextAuth, { DefaultSession } from "next-auth";
declare module "next-auth" {
/**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
*/
interface Session {
user: {
accessToken: string;
userId: number;
} & DefaultSession["user"];
}
}
@DanProudfoot
Copy link

This saved me so much time, thank you!

@thevisioner
Copy link
Author

This saved me so much time, thank you!

Great! 👍

@ukarulis
Copy link

Legend! I am glad that I decided to read comments first in Strapi official documentation. Took 15 minutes to set up :)

@Imtbdev
Copy link

Imtbdev commented Mar 31, 2024

Please update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment