diff --git a/demos/next-auth/.env.local.example b/demos/next-auth/.env.local.example new file mode 100644 index 0000000000..83cb4bc2d5 --- /dev/null +++ b/demos/next-auth/.env.local.example @@ -0,0 +1,4 @@ +NEXTAUTH_URL=http://localhost:3000 + +NETLIFY_CLIENT_ID= +NETLIFY_CLIENT_SECRET= diff --git a/demos/next-auth/.eslintrc b/demos/next-auth/.eslintrc new file mode 100644 index 0000000000..abd5579b49 --- /dev/null +++ b/demos/next-auth/.eslintrc @@ -0,0 +1,4 @@ +{ + "extends": "next", + "root": true +} diff --git a/demos/next-auth/.gitignore b/demos/next-auth/.gitignore new file mode 100644 index 0000000000..c6bba59138 --- /dev/null +++ b/demos/next-auth/.gitignore @@ -0,0 +1,130 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/demos/next-auth/LICENSE b/demos/next-auth/LICENSE new file mode 100644 index 0000000000..eee418eafa --- /dev/null +++ b/demos/next-auth/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2018-2021, Iain Collins + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/demos/next-auth/README.md b/demos/next-auth/README.md new file mode 100644 index 0000000000..c29a79f6f8 --- /dev/null +++ b/demos/next-auth/README.md @@ -0,0 +1,34 @@ +## NextAuth.js Example + +This example project came from [next-auth-example](https://github.com/nextauthjs/next-auth-example) provided by the NextAuth.js and was modified to use Netlify as the authentication provider as an example. + +For more details on how to get set up and configured with various providers, visit the link above. + +### Running locally + +Within this project directory: + +``` +npm install +npm run dev +``` + +### Configuring your local environment + +Copy the .env.local.example file in this directory to .env.local (which will be ignored by Git): + +``` +cp .env.local.example .env.local +``` + +Add details for the [Netlify Provider](https://next-auth.js.org/providers/netlify), which will require create a Netlify OAuth application. + +To create a Netlify OAuth application: +* Visit `https://app.netlify.com/user/applications` +* Click 'New OAuth App' +* Enter an application name +* Enter a redirect URI (for the purposes of this demo application you would use `http://localhost:3000/api/auth/callback/netlify`) +* Save the application, and copy the value for 'Client ID' as the `NETLIFY_CLIENT_ID` and the 'Client Secret' as the `NETLIFY_CLIENT_SECRET` into your `.env.local` file within the project + * If you're testing this on a deployed Netlify site you'll need to set the environment variables as part of the `Site Settings > Build & Deploy > Environment` settings. You'll also need to generate a `NEXTAUTH_SECRET` environment variable and set that for a production build. + +For configuring additional authentication providers, see the original documentation [here](https://github.com/nextauthjs/next-auth-example#3-configure-authentication-providers) diff --git a/demos/next-auth/components/access-denied.tsx b/demos/next-auth/components/access-denied.tsx new file mode 100644 index 0000000000..4c9c0d7947 --- /dev/null +++ b/demos/next-auth/components/access-denied.tsx @@ -0,0 +1,20 @@ +import { signIn } from "next-auth/react" + +export default function AccessDenied() { + return ( + <> +

Access Denied

+

+ { + e.preventDefault() + signIn() + }} + > + You must be signed in to view this page + +

+ + ) +} diff --git a/demos/next-auth/components/footer.module.css b/demos/next-auth/components/footer.module.css new file mode 100644 index 0000000000..020bec6415 --- /dev/null +++ b/demos/next-auth/components/footer.module.css @@ -0,0 +1,14 @@ +.footer { + margin-top: 2rem; +} + +.navItems { + margin-bottom: 1rem; + padding: 0; + list-style: none; +} + +.navItem { + display: inline-block; + margin-right: 1rem; +} diff --git a/demos/next-auth/components/footer.tsx b/demos/next-auth/components/footer.tsx new file mode 100644 index 0000000000..e01b64f198 --- /dev/null +++ b/demos/next-auth/components/footer.tsx @@ -0,0 +1,30 @@ +import Link from "next/link" +import styles from "./footer.module.css" +import packageJSON from "../package.json" + +export default function Footer() { + return ( + + ) +} diff --git a/demos/next-auth/components/header.module.css b/demos/next-auth/components/header.module.css new file mode 100644 index 0000000000..773478c6af --- /dev/null +++ b/demos/next-auth/components/header.module.css @@ -0,0 +1,92 @@ +/* Set min-height to avoid page reflow while session loading */ +.signedInStatus { + display: block; + min-height: 4rem; + width: 100%; +} + +.loading, +.loaded { + position: relative; + top: 0; + opacity: 1; + overflow: hidden; + border-radius: 0 0 0.6rem 0.6rem; + padding: 0.6rem 1rem; + margin: 0; + background-color: rgba(0, 0, 0, 0.05); + transition: all 0.2s ease-in; +} + +.loading { + top: -2rem; + opacity: 0; +} + +.signedInText, +.notSignedInText { + position: absolute; + padding-top: 0.8rem; + left: 1rem; + right: 6.5rem; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + display: inherit; + z-index: 1; + line-height: 1.3rem; +} + +.signedInText { + padding-top: 0rem; + left: 4.6rem; +} + +.avatar { + border-radius: 2rem; + float: left; + height: 2.8rem; + width: 2.8rem; + background-color: white; + background-size: cover; + background-repeat: no-repeat; +} + +.button, +.buttonPrimary { + float: right; + margin-right: -0.4rem; + font-weight: 500; + border-radius: 0.3rem; + cursor: pointer; + font-size: 1rem; + line-height: 1.4rem; + padding: 0.7rem 0.8rem; + position: relative; + z-index: 10; + background-color: transparent; + color: #555; +} + +.buttonPrimary { + background-color: #346df1; + border-color: #346df1; + color: #fff; + text-decoration: none; + padding: 0.7rem 1.4rem; +} + +.buttonPrimary:hover { + box-shadow: inset 0 0 5rem rgba(0, 0, 0, 0.2); +} + +.navItems { + margin-bottom: 2rem; + padding: 0; + list-style: none; +} + +.navItem { + display: inline-block; + margin-right: 1rem; +} diff --git a/demos/next-auth/components/header.tsx b/demos/next-auth/components/header.tsx new file mode 100644 index 0000000000..8fed732d72 --- /dev/null +++ b/demos/next-auth/components/header.tsx @@ -0,0 +1,108 @@ +import Link from "next/link" +import { signIn, signOut, useSession } from "next-auth/react" +import styles from "./header.module.css" + +// The approach used in this component shows how to build a sign in and sign out +// component that works on pages which support both client and server side +// rendering, and avoids any flash incorrect content on initial page load. +export default function Header() { + const { data: session, status } = useSession() + const loading = status === "loading" + + return ( +
+ +
+

+ {!session && ( + <> + + You are not signed in + + { + e.preventDefault() + signIn() + }} + > + Sign in + + + )} + {session?.user && ( + <> + {session.user.image && ( + + )} + + Signed in as +
+ {session.user.email ?? session.user.name} +
+ { + e.preventDefault() + signOut() + }} + > + Sign out + + + )} +

+
+ +
+ ) +} diff --git a/demos/next-auth/components/layout.tsx b/demos/next-auth/components/layout.tsx new file mode 100644 index 0000000000..8495690ad5 --- /dev/null +++ b/demos/next-auth/components/layout.tsx @@ -0,0 +1,17 @@ +import Header from "./header" +import Footer from "./footer" +import type { ReactChildren } from "react" + +interface Props { + children: React.ReactNode +} + +export default function Layout({ children }: Props) { + return ( + <> +
+
{children}
+