to improve performance and allow components that call
6 | // `useSession()` anywhere in your application to access the `session` object.
7 | export default function App({ Component, pageProps }: AppProps) {
8 | return (
9 |
14 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/pages/api-example.tsx:
--------------------------------------------------------------------------------
1 | import Layout from '../components/layout'
2 |
3 | export default function Page () {
4 | return (
5 |
6 | API Example
7 | The examples below show responses from the example API endpoints.
8 | You must be signed in to see responses.
9 | Session
10 | /api/examples/session
11 |
12 | JSON Web Token
13 | /api/examples/jwt
14 |
15 |
16 | )
17 | }
--------------------------------------------------------------------------------
/pages/api/auth/[...nextauth].ts:
--------------------------------------------------------------------------------
1 | import NextAuth from "next-auth"
2 | import Auth0Provider from "next-auth/providers/auth0"
3 | import FacebookProvider from "next-auth/providers/facebook"
4 | import GithubProvider from "next-auth/providers/github"
5 | import GoogleProvider from "next-auth/providers/google"
6 | import TwitterProvider from "next-auth/providers/twitter"
7 | // import EmailProvider from "next-auth/providers/email"
8 | // import AppleProvider from "next-auth/providers/apple"
9 |
10 | // For more information on each option (and a full list of options) go to
11 | // https://next-auth.js.org/configuration/options
12 | export default NextAuth({
13 | // https://next-auth.js.org/configuration/providers
14 | providers: [
15 | // EmailProvider({
16 | // server: process.env.EMAIL_SERVER,
17 | // from: process.env.EMAIL_FROM,
18 | // }),
19 | // AppleProvider({
20 | // clientId: process.env.APPLE_ID,
21 | // clientSecret: {
22 | // appleId: process.env.APPLE_ID,
23 | // teamId: process.env.APPLE_TEAM_ID,
24 | // privateKey: process.env.APPLE_PRIVATE_KEY,
25 | // keyId: process.env.APPLE_KEY_ID,
26 | // },
27 | // }),
28 | Auth0Provider({
29 | clientId: process.env.AUTH0_ID,
30 | clientSecret: process.env.AUTH0_SECRET,
31 | // @ts-ignore
32 | domain: process.env.AUTH0_DOMAIN,
33 | }),
34 | FacebookProvider({
35 | clientId: process.env.FACEBOOK_ID,
36 | clientSecret: process.env.FACEBOOK_SECRET,
37 | }),
38 | GithubProvider({
39 | clientId: process.env.GITHUB_ID,
40 | clientSecret: process.env.GITHUB_SECRET,
41 | // https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps
42 | // @ts-ignore
43 | scope: "read:user",
44 | }),
45 | GoogleProvider({
46 | clientId: process.env.GOOGLE_ID,
47 | clientSecret: process.env.GOOGLE_SECRET,
48 | }),
49 | TwitterProvider({
50 | clientId: process.env.TWITTER_ID,
51 | clientSecret: process.env.TWITTER_SECRET,
52 | }),
53 | ],
54 | // Database optional. MySQL, Maria DB, Postgres and MongoDB are supported.
55 | // https://next-auth.js.org/configuration/databases
56 | //
57 | // Notes:
58 | // * You must install an appropriate node_module for your database
59 | // * The Email provider requires a database (OAuth providers do not)
60 | // database: process.env.DATABASE_URL,
61 |
62 | // The secret should be set to a reasonably long random string.
63 | // It is used to sign cookies and to sign and encrypt JSON Web Tokens, unless
64 | // a separate secret is defined explicitly for encrypting the JWT.
65 | secret: process.env.SECRET,
66 |
67 | session: {
68 | // Use JSON Web Tokens for session instead of database sessions.
69 | // This option can be used with or without a database for users/accounts.
70 | // Note: `strategy` should be set to 'jwt' if no database is used.
71 | strategy: 'jwt'
72 |
73 | // Seconds - How long until an idle session expires and is no longer valid.
74 | // maxAge: 30 * 24 * 60 * 60, // 30 days
75 |
76 | // Seconds - Throttle how frequently to write to database to extend a session.
77 | // Use it to limit write operations. Set to 0 to always update the database.
78 | // Note: This option is ignored if using JSON Web Tokens
79 | // updateAge: 24 * 60 * 60, // 24 hours
80 | },
81 |
82 | // JSON Web tokens are only used for sessions if the `strategy: 'jwt'` session
83 | // option is set - or by default if no database is specified.
84 | // https://next-auth.js.org/configuration/options#jwt
85 | jwt: {
86 | // A secret to use for key generation (you should set this explicitly)
87 | secret: process.env.SECRET,
88 | // Set to true to use encryption (default: false)
89 | // encryption: true,
90 | // You can define your own encode/decode functions for signing and encryption
91 | // if you want to override the default behaviour.
92 | // encode: async ({ secret, token, maxAge }) => {},
93 | // decode: async ({ secret, token, maxAge }) => {},
94 | },
95 |
96 | // You can define custom pages to override the built-in ones. These will be regular Next.js pages
97 | // so ensure that they are placed outside of the '/api' folder, e.g. signIn: '/auth/mycustom-signin'
98 | // The routes shown here are the default URLs that will be used when a custom
99 | // pages is not specified for that route.
100 | // https://next-auth.js.org/configuration/pages
101 | pages: {
102 | // signIn: '/auth/signin', // Displays signin buttons
103 | // signOut: '/auth/signout', // Displays form with sign out button
104 | // error: '/auth/error', // Error code passed in query string as ?error=
105 | // verifyRequest: '/auth/verify-request', // Used for check email page
106 | // newUser: null // If set, new users will be directed here on first sign in
107 | },
108 |
109 | // Callbacks are asynchronous functions you can use to control what happens
110 | // when an action is performed.
111 | // https://next-auth.js.org/configuration/callbacks
112 | callbacks: {
113 | // async signIn({ user, account, profile, email, credentials }) { return true },
114 | // async redirect({ url, baseUrl }) { return baseUrl },
115 | // async session({ session, token, user }) { return session },
116 | // async jwt({ token, user, account, profile, isNewUser }) { return token }
117 | },
118 |
119 | // Events are useful for logging
120 | // https://next-auth.js.org/configuration/events
121 | events: {},
122 |
123 | // Enable debug messages in the console if you are having problems
124 | debug: false,
125 | })
126 |
--------------------------------------------------------------------------------
/pages/api/examples/jwt.ts:
--------------------------------------------------------------------------------
1 | // This is an example of how to read a JSON Web Token from an API route
2 | import { getToken } from "next-auth/jwt"
3 | import type { NextApiRequest, NextApiResponse } from "next"
4 |
5 | const secret = process.env.SECRET
6 |
7 | export default async function jwt(req: NextApiRequest, res: NextApiResponse) {
8 | const token = await getToken({ req, secret })
9 | res.send(JSON.stringify(token, null, 2))
10 | }
11 |
--------------------------------------------------------------------------------
/pages/api/examples/protected.ts:
--------------------------------------------------------------------------------
1 | // This is an example of to protect an API route
2 | import { getSession } from "next-auth/react"
3 | import type { NextApiRequest, NextApiResponse } from "next"
4 |
5 | export default async function protectedHandler(
6 | req: NextApiRequest,
7 | res: NextApiResponse
8 | ) {
9 | const session = await getSession({ req })
10 |
11 | if (session) {
12 | return res.send({
13 | content:
14 | "This is protected content. You can access this content because you are signed in.",
15 | })
16 | }
17 |
18 | res.send({
19 | error: "You must be sign in to view the protected content on this page.",
20 | })
21 | }
22 |
--------------------------------------------------------------------------------
/pages/api/examples/session.ts:
--------------------------------------------------------------------------------
1 | // This is an example of how to access a session from an API route
2 | import { getSession } from "next-auth/react"
3 | import type { NextApiRequest, NextApiResponse } from "next"
4 |
5 | export default async function session(
6 | req: NextApiRequest,
7 | res: NextApiResponse
8 | ) {
9 | const session = await getSession({ req })
10 | res.send(JSON.stringify(session, null, 2))
11 | }
12 |
--------------------------------------------------------------------------------
/pages/client.tsx:
--------------------------------------------------------------------------------
1 | import Layout from '../components/layout'
2 |
3 | export default function Page () {
4 | return (
5 |
6 | Client Side Rendering
7 |
8 | This page uses the useSession() React Hook in the <Header/> component.
9 |
10 |
11 | The useSession() React Hook is easy to use and allows pages to render very quickly.
12 |
13 |
14 | The advantage of this approach is that session state is shared between pages by using the Provider in _app.js so
15 | that navigation between pages using useSession() is very fast.
16 |
17 |
18 | The disadvantage of useSession() is that it requires client side JavaScript.
19 |
20 |
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import Layout from '../components/layout'
2 |
3 | export default function Page () {
4 | return (
5 |
6 | NextAuth.js Example
7 |
8 | This is an example site to demonstrate how to use NextAuth.js for authentication.
9 |
10 |
11 | )
12 | }
--------------------------------------------------------------------------------
/pages/policy.tsx:
--------------------------------------------------------------------------------
1 | import Layout from '../components/layout'
2 |
3 | export default function Page () {
4 | return (
5 |
6 |
7 | This is an example site to demonstrate how to use NextAuth.js for authentication.
8 |
9 | Terms of Service
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 | SOFTWARE.
18 |
19 | Privacy Policy
20 |
21 | This site uses JSON Web Tokens and an in-memory database which resets every ~2 hours.
22 |
23 |
24 | Data provided to this site is exclusively used to support signing in
25 | and is not passed to any third party services, other than via SMTP or OAuth for the
26 | purposes of authentication.
27 |
28 |
29 | )
30 | }
--------------------------------------------------------------------------------
/pages/protected.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react'
2 | import { useSession } from 'next-auth/react'
3 | import Layout from '../components/layout'
4 | import AccessDenied from '../components/access-denied'
5 |
6 | export default function Page () {
7 | const { data: session, status } = useSession()
8 | const loading = status === 'loading'
9 | const [ content , setContent ] = useState()
10 |
11 | // Fetch content from protected route
12 | useEffect(()=>{
13 | const fetchData = async () => {
14 | const res = await fetch('/api/examples/protected')
15 | const json = await res.json()
16 | if (json.content) { setContent(json.content) }
17 | }
18 | fetchData()
19 | },[session])
20 |
21 | // When rendering client side don't display anything until loading is complete
22 | if (typeof window !== 'undefined' && loading) return null
23 |
24 | // If no session exists, display access denied message
25 | if (!session) { return }
26 |
27 | // If session exists, display content
28 | return (
29 |
30 | Protected Page
31 | {content || "\u00a0"}
32 |
33 | )
34 | }
35 |
--------------------------------------------------------------------------------
/pages/server.tsx:
--------------------------------------------------------------------------------
1 | import { GetServerSideProps } from "next"
2 | import type { Session } from "next-auth"
3 | import { useSession, getSession } from "next-auth/react"
4 | import Layout from "../components/layout"
5 |
6 | export default function Page() {
7 | // As this page uses Server Side Rendering, the `session` will be already
8 | // populated on render without needing to go through a loading stage.
9 | // This is possible because of the shared context configured in `_app.js` that
10 | // is used by `useSession()`.
11 | const { data: session, status } = useSession()
12 | const loading = status === 'loading'
13 |
14 | return (
15 |
16 | Server Side Rendering
17 |
18 | This page uses the universal getSession() method in{" "}
19 | getServerSideProps().
20 |
21 |
22 | Using getSession() in{" "}
23 | getServerSideProps() is the recommended approach if you
24 | need to support Server Side Rendering with authentication.
25 |
26 |
27 | The advantage of Server Side Rendering is this page does not require
28 | client side JavaScript.
29 |
30 |
31 | The disadvantage of Server Side Rendering is that this page is slower to
32 | render.
33 |
34 |
35 | )
36 | }
37 |
38 | // Export the `session` prop to use sessions with Server Side Rendering
39 | export const getServerSideProps: GetServerSideProps<{
40 | session: Session | null
41 | }> = async (context) => {
42 | return {
43 | props: {
44 | session: await getSession(context),
45 | },
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/pages/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
3 | padding: 0 1rem 1rem 1rem;
4 | max-width: 680px;
5 | margin: 0 auto;
6 | background: #fff;
7 | color: #333;
8 | }
9 |
10 | li,
11 | p {
12 | line-height: 1.5rem;
13 | }
14 |
15 | a {
16 | font-weight: 500;
17 | }
18 |
19 | hr {
20 | border: 1px solid #ddd;
21 | }
22 |
23 | iframe {
24 | background: #ccc;
25 | border: 1px solid #ccc;
26 | height: 10rem;
27 | width: 100%;
28 | border-radius: .5rem;
29 | filter: invert(1);
30 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve"
16 | },
17 | "include": ["types/**/*.ts", "**/*.ts", "**/*.tsx"],
18 | "exclude": ["node_modules"]
19 | }
20 |
--------------------------------------------------------------------------------
/types/environment.d.ts:
--------------------------------------------------------------------------------
1 | namespace NodeJS {
2 | interface ProcessEnv extends NodeJS.ProcessEnv {
3 | EMAIL_SERVER: string
4 | EMAIL_FROM: string
5 | APPLE_ID: string
6 | APPLE_TEAM_ID: string
7 | APPLE_PRIVATE_KEY: string
8 | APPLE_KEY_ID: string
9 | AUTH0_ID: string
10 | AUTH0_SECRET: string
11 | AUTH0_DOMAIN: string
12 | FACEBOOK_ID: string
13 | FACEBOOK_SECRET: string
14 | GITHUB_ID: string
15 | GITHUB_SECRET: string
16 | GOOGLE_ID: string
17 | GOOGLE_SECRET: string
18 | TWITTER_ID: string
19 | TWITTER_SECRET: string
20 | DATABASE_URL: string
21 | SECRET: string
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/types/next-auth.d.ts:
--------------------------------------------------------------------------------
1 | import { Session } from "next-auth"
2 | import { JWT } from "next-auth/jwt"
3 |
4 | /** Example on how to extend the built-in session types */
5 | declare module "next-auth" {
6 | interface Session {
7 | /** This is an example. You can find me in types/next-auth.d.ts */
8 | foo: string
9 | }
10 | }
11 |
12 | /** Example on how to extend the built-in types for JWT */
13 | declare module "next-auth/jwt" {
14 | interface JWT {
15 | /** This is an example. You can find me in types/next-auth.d.ts */
16 | bar: number
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/types/next.d.ts:
--------------------------------------------------------------------------------
1 | import type { NextComponentType, NextPageContext } from "next"
2 | import type { Session } from "next-auth"
3 | import type { Router } from "next/router"
4 |
5 | declare module "next/app" {
6 | type AppProps> = {
7 | Component: NextComponentType
8 | router: Router
9 | __N_SSG?: boolean
10 | __N_SSP?: boolean
11 | pageProps: P & {
12 | /** Initial session passed in from `getServerSideProps` or `getInitialProps` */
13 | session?: Session
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------