mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
95 Commits
next-auth@
...
@auth/core
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aad0b8db0e | ||
|
|
137bbb8d84 | ||
|
|
d7fbd05eba | ||
|
|
532aa24495 | ||
|
|
f5da5a5f33 | ||
|
|
3b85f46c21 | ||
|
|
6aa1af2ffb | ||
|
|
9364625681 | ||
|
|
1bf2e1d468 | ||
|
|
ac304f17da | ||
|
|
3a685b28f8 | ||
|
|
5b34b95c58 | ||
|
|
a706105205 | ||
|
|
39c78f27b5 | ||
|
|
b179f15cf3 | ||
|
|
54561a1231 | ||
|
|
0ea9ada3a9 | ||
|
|
209c368a73 | ||
|
|
52c5b7cad3 | ||
|
|
b8d83f52b3 | ||
|
|
7dacfbabf0 | ||
|
|
bb372cc5cc | ||
|
|
c6ca01a99e | ||
|
|
6c45abf383 | ||
|
|
2ba5314e35 | ||
|
|
582a3c339a | ||
|
|
ea23a93442 | ||
|
|
1d67ad41cc | ||
|
|
7c50b3da98 | ||
|
|
1b2c373fa1 | ||
|
|
f7275c7527 | ||
|
|
e699ff14b8 | ||
|
|
6eab7ac25f | ||
|
|
9b05dbc540 | ||
|
|
132a76d951 | ||
|
|
66cbb522d9 | ||
|
|
553924d902 | ||
|
|
cba81f0b8c | ||
|
|
b7171ab790 | ||
|
|
43c8f663c6 | ||
|
|
b16b048991 | ||
|
|
62a5d70f9b | ||
|
|
1b671ae83d | ||
|
|
cc4b9fc2fc | ||
|
|
4935166372 | ||
|
|
695f937dbd | ||
|
|
ad9eec3676 | ||
|
|
2e924edcdf | ||
|
|
c7627778eb | ||
|
|
8b5644453b | ||
|
|
84291d3e81 | ||
|
|
67e5c236f6 | ||
|
|
8972defa4b | ||
|
|
85667dd681 | ||
|
|
d9532745eb | ||
|
|
1e6daa8304 | ||
|
|
70a3e3f662 | ||
|
|
875f79d11e | ||
|
|
6cfe502ae0 | ||
|
|
91c6b05ed8 | ||
|
|
45a18930c8 | ||
|
|
6f22a49c7d | ||
|
|
fea30069c9 | ||
|
|
cd01707530 | ||
|
|
d9a2df3a3d | ||
|
|
f4a1ed1eb7 | ||
|
|
a97737cc18 | ||
|
|
b44d1a005e | ||
|
|
2c077e1491 | ||
|
|
19804661d2 | ||
|
|
b7f1e3e7f8 | ||
|
|
7757024d79 | ||
|
|
3f15dc67e1 | ||
|
|
5359694b8f | ||
|
|
66686fa5fc | ||
|
|
1d6330b719 | ||
|
|
0eb20d1097 | ||
|
|
ac30402c6a | ||
|
|
caa6c6ae42 | ||
|
|
a6ac48314e | ||
|
|
f8675bc245 | ||
|
|
3d4842dcc9 | ||
|
|
7d7d1b2f80 | ||
|
|
9a4f3db7b0 | ||
|
|
6aad07a95c | ||
|
|
cfed5b976f | ||
|
|
d34108091f | ||
|
|
7bf79b89a8 | ||
|
|
4cd688703a | ||
|
|
57b176840e | ||
|
|
6298d955df | ||
|
|
2ad1cb3f8c | ||
|
|
98707282eb | ||
|
|
f4a2430891 | ||
|
|
575bcb5710 |
70
.eslintrc.js
70
.eslintrc.js
@@ -1,20 +1,21 @@
|
||||
// @ts-check
|
||||
const path = require("path")
|
||||
|
||||
/** @type {import("eslint").ESLint.ConfigData} */
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: "@typescript-eslint/parser",
|
||||
extends: ["standard-with-typescript", "prettier"],
|
||||
rules: {
|
||||
camelcase: "off",
|
||||
"@typescript-eslint/naming-convention": "off",
|
||||
"@typescript-eslint/strict-boolean-expressions": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/restrict-template-expressions": "off",
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.ts", "*.tsx"],
|
||||
extends: ["standard-with-typescript", "prettier"],
|
||||
rules: {
|
||||
camelcase: "off",
|
||||
"@typescript-eslint/naming-convention": "off",
|
||||
"@typescript-eslint/strict-boolean-expressions": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/restrict-template-expressions": "off",
|
||||
},
|
||||
|
||||
parserOptions: {
|
||||
project: [
|
||||
path.resolve(__dirname, "./packages/**/tsconfig.eslint.json"),
|
||||
@@ -23,19 +24,44 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["*.test.ts", "*.test.js"],
|
||||
env: { jest: true },
|
||||
},
|
||||
{
|
||||
files: ["docs/**"],
|
||||
plugins: ["@docusaurus"],
|
||||
extends: ["plugin:@docusaurus/recommended"],
|
||||
},
|
||||
{
|
||||
files: ["packages/core/src/**/*"],
|
||||
plugins: ["jsdoc"],
|
||||
extends: ["plugin:jsdoc/recommended"],
|
||||
rules: {
|
||||
"jsdoc/require-param": "off",
|
||||
"jsdoc/require-returns": "off",
|
||||
"jsdoc/require-jsdoc": [
|
||||
"warn",
|
||||
{ publicOnly: true, enableFixer: false },
|
||||
],
|
||||
"jsdoc/no-multi-asterisks": ["warn", { allowWhitespace: true }],
|
||||
"jsdoc/tag-lines": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["packages/core/src/adapters.ts"],
|
||||
rules: {
|
||||
"@typescript-eslint/method-signature-style": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
extends: ["prettier"],
|
||||
globals: {
|
||||
localStorage: "readonly",
|
||||
location: "readonly",
|
||||
fetch: "readonly",
|
||||
},
|
||||
rules: {
|
||||
camelcase: "off",
|
||||
},
|
||||
plugins: ["jest"],
|
||||
env: {
|
||||
"jest/globals": true,
|
||||
},
|
||||
ignorePatterns: [".eslintrc.js"],
|
||||
ignorePatterns: [
|
||||
"**/dist/**",
|
||||
"**/node_modules/**",
|
||||
".eslintrc.js",
|
||||
"**/.turbo/**",
|
||||
"**/coverage/**",
|
||||
"**/build/**",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -4,11 +4,8 @@ import * as github from "@actions/github"
|
||||
// @ts-expect-error
|
||||
import * as core from "@actions/core"
|
||||
import { readFileSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
|
||||
const addReproductionLabel = "incomplete"
|
||||
const __dirname =
|
||||
"/home/runner/work/nextauthjs/next-auth/.github/actions/issue-validator"
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
@@ -73,7 +70,7 @@ async function run() {
|
||||
}),
|
||||
client.issues.createComment({
|
||||
...issueCommon,
|
||||
body: readFileSync(join(__dirname, "repro.md"), "utf8"),
|
||||
body: readFileSync("repro.md", "utf8"),
|
||||
}),
|
||||
])
|
||||
return core.info(
|
||||
|
||||
2
.github/pr-labeler.yml
vendored
2
.github/pr-labeler.yml
vendored
@@ -54,7 +54,7 @@ upstash-redis:
|
||||
xata:
|
||||
- packages/adapter-xata/**
|
||||
|
||||
legacy:
|
||||
core:
|
||||
- packages/next-auth/src/**/*
|
||||
|
||||
style:
|
||||
|
||||
15
.github/sync.yml
vendored
Normal file
15
.github/sync.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Note that nextauthjs/next-auth-example syncs from the v4 branch
|
||||
|
||||
nextauthjs/sveltekit-auth-example:
|
||||
- source: apps/example-sveltekit
|
||||
dest: .
|
||||
deleteOrphaned: true
|
||||
- .github/FUNDING.yml
|
||||
- LICENSE
|
||||
|
||||
nextauthjs/next-auth-gatsby-example:
|
||||
- source: apps/playground-gatsby
|
||||
dest: .
|
||||
deleteOrphaned: true
|
||||
- .github/FUNDING.yml
|
||||
- LICENSE
|
||||
6
.github/workflows/issue-validator.yml
vendored
6
.github/workflows/issue-validator.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: 'Run issue validator'
|
||||
run: node ./.github/actions/issue-validator/index.mjs
|
||||
- name: "Run issue validator"
|
||||
run: node /home/runner/work/next-auth/next-auth/.github/actions/issue-validator/index.mjs
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
37
.github/workflows/release.yml
vendored
37
.github/workflows/release.yml
vendored
@@ -7,7 +7,6 @@ on:
|
||||
- "beta"
|
||||
- "next"
|
||||
- "3.x"
|
||||
- "v4"
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
@@ -30,18 +29,11 @@ jobs:
|
||||
cache: "pnpm"
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
- name: Run tests
|
||||
run: pnpm test
|
||||
env:
|
||||
UPSTASH_REDIS_URL: ${{ secrets.UPSTASH_REDIS_URL }}
|
||||
UPSTASH_REDIS_KEY: ${{ secrets.UPSTASH_REDIS_KEY }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
# - name: Coverage
|
||||
# uses: codecov/codecov-action@v1
|
||||
# with:
|
||||
@@ -58,6 +50,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GH_PAT_CLASSIC }}
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
with:
|
||||
@@ -70,15 +63,12 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
- name: Publish to npm and GitHub
|
||||
run: |
|
||||
git config --global user.email "balazsorban44@users.noreply.github.com"
|
||||
git config --global user.name "Balázs Orbán"
|
||||
pnpm release
|
||||
run: pnpm release
|
||||
env:
|
||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
NPM_TOKEN_PKG: ${{ secrets.NPM_TOKEN_PKG }}
|
||||
NPM_TOKEN_ORG: ${{ secrets.NPM_TOKEN_ORG }}
|
||||
# Use GH_PAT when this is fixed:
|
||||
# https://github.com/github/roadmap/issues/622
|
||||
GITHUB_TOKEN: ${{ secrets.GH_PAT_CLASSIC }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
release-pr:
|
||||
name: Publish PR
|
||||
runs-on: ubuntu-latest
|
||||
@@ -106,19 +96,20 @@ jobs:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
cd packages/next-auth
|
||||
cd packages/core
|
||||
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc
|
||||
pnpm publish --no-git-checks --access public --tag experimental
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN_PKG }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Comment version on PR
|
||||
uses: NejcZdovc/comment-pr@v2
|
||||
with:
|
||||
message:
|
||||
"🎉 Experimental release [published 📦️ on npm](https://npmjs.com/package/next-auth/v/${{ env.VERSION }})!\n \
|
||||
```sh\npnpm add next-auth@${{ env.VERSION }}\n```\n \
|
||||
```sh\nyarn add next-auth@${{ env.VERSION }}\n```\n \
|
||||
```sh\nnpm i next-auth@${{ env.VERSION }}\n```"
|
||||
"🎉 Experimental release [published 📦️ on npm](https://npmjs.com/package/@auth/core/v/${{ env.VERSION }})!\n \
|
||||
```sh\npnpm add @auth/core@${{ env.VERSION }}\n```\n \
|
||||
```sh\nyarn add @auth/core@${{ env.VERSION }}\n```\n \
|
||||
```sh\nnpm i @auth/core@${{ env.VERSION }}\n```"
|
||||
env:
|
||||
VERSION: ${{ steps.determine-version.outputs.version }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
|
||||
|
||||
|
||||
19
.github/workflows/sync-examples.yml
vendored
Normal file
19
.github/workflows/sync-examples.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Sync Example Repositories
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Run GitHub File Sync
|
||||
# Can update to v1 when https://github.com/BetaHuhn/repo-file-sync-action/issues/168 is resolved
|
||||
uses: BetaHuhn/repo-file-sync-action@v1.16.5
|
||||
with:
|
||||
GH_PAT: ${{ secrets.SYNC_EXAMPLE_PAT }}
|
||||
SKIP_PR: true
|
||||
ORIGINAL_MESSAGE: true
|
||||
18
.gitignore
vendored
18
.gitignore
vendored
@@ -34,9 +34,13 @@ packages/next-auth/utils
|
||||
packages/next-auth/core
|
||||
packages/next-auth/jwt
|
||||
packages/next-auth/react
|
||||
packages/next-auth/*.d.ts*
|
||||
packages/next-auth/*.js
|
||||
packages/next-auth/adapters.d.ts
|
||||
packages/next-auth/adapters.js
|
||||
packages/next-auth/index.d.ts
|
||||
packages/next-auth/index.js
|
||||
packages/next-auth/next
|
||||
packages/next-auth/middleware.d.ts
|
||||
packages/next-auth/middleware.js
|
||||
|
||||
# Development app
|
||||
apps/dev/src/css
|
||||
@@ -47,7 +51,7 @@ apps/dev/typeorm
|
||||
/.vs/slnx.sqlite-journal
|
||||
/.vs/slnx.sqlite
|
||||
/.vs
|
||||
.vscode
|
||||
.vscode/generated*
|
||||
|
||||
# Jetbrains
|
||||
.idea
|
||||
@@ -77,11 +81,13 @@ docs/.docusaurus
|
||||
docs/providers.json
|
||||
|
||||
# Core
|
||||
packages/core/adapters.*
|
||||
packages/core/index.*
|
||||
packages/core/jwt
|
||||
packages/core/*.js
|
||||
packages/core/*.d.ts
|
||||
packages/core/*.d.ts.map
|
||||
packages/core/lib
|
||||
packages/core/providers
|
||||
docs/docs/reference/03-core
|
||||
docs/docs/reference/04-sveltekit
|
||||
|
||||
|
||||
# SvelteKit
|
||||
|
||||
16
.prettierrc.js
Normal file
16
.prettierrc.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// @ts-check
|
||||
|
||||
/** @type {import("prettier").Config} */
|
||||
module.exports = {
|
||||
semi: false,
|
||||
singleQuote: false,
|
||||
overrides: [
|
||||
{
|
||||
files: [
|
||||
"apps/dev/pages/api/auth/[...nextauth].ts",
|
||||
"docs/{sidebars,docusaurus.config}.js",
|
||||
],
|
||||
options: { printWidth: 150 },
|
||||
},
|
||||
],
|
||||
}
|
||||
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"files.exclude": {
|
||||
"packages/core/{lib,providers,*.js,*.d.ts,*.d.ts.map}": true,
|
||||
"packages/next-auth/{client,core,css,jwt,next,providers,react,utils,*.js,*.d.ts}": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"openInGitHub.remote.branch": "main",
|
||||
}
|
||||
18
.vscode/snippets.code-snippets
vendored
Normal file
18
.vscode/snippets.code-snippets
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"oauth2-spec": {
|
||||
"description": "Markdown link to OAuth 2 specification",
|
||||
"scope": "typescript",
|
||||
"prefix": "oauth2",
|
||||
"body": [
|
||||
"[OAuth 2](https://datatracker.ietf.org/doc/html/rfc6749)"
|
||||
]
|
||||
},
|
||||
"oidc-spec": {
|
||||
"description": "Markdown link to OpenID Connect specification",
|
||||
"scope": "typescript",
|
||||
"prefix": "oidc",
|
||||
"body": [
|
||||
"[OIDC](https://openid.net/specs/openid-connect-core-1_0.html)"
|
||||
]
|
||||
},
|
||||
}
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2018-2021, Iain Collins
|
||||
Copyright (c) 2022-2023, Balázs Orbán
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
|
||||
4
apps/dev/.vscode/settings.json
vendored
Normal file
4
apps/dev/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"typescript.tsdk": "../../node_modules/.pnpm/typescript@4.8.4/node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
import NextAuth, { type NextAuthOptions } from "next-auth"
|
||||
// import { NextRequest } from "next/server"
|
||||
|
||||
// Providers
|
||||
import Apple from "next-auth/providers/apple"
|
||||
import Auth0 from "next-auth/providers/auth0"
|
||||
import AzureAD from "next-auth/providers/azure-ad"
|
||||
import AzureB2C from "next-auth/providers/azure-ad-b2c"
|
||||
import BoxyHQSAML from "next-auth/providers/boxyhq-saml"
|
||||
// import Cognito from "next-auth/providers/cognito"
|
||||
import Credentials from "next-auth/providers/credentials"
|
||||
import Discord from "next-auth/providers/discord"
|
||||
import DuendeIDS6 from "next-auth/providers/duende-identity-server6"
|
||||
// import Email from "next-auth/providers/email"
|
||||
import Facebook from "next-auth/providers/facebook"
|
||||
import Foursquare from "next-auth/providers/foursquare"
|
||||
import Freshbooks from "next-auth/providers/freshbooks"
|
||||
import GitHub from "next-auth/providers/github"
|
||||
import Gitlab from "next-auth/providers/gitlab"
|
||||
import Google from "next-auth/providers/google"
|
||||
// import IDS4 from "next-auth/providers/identity-server4"
|
||||
import Instagram from "next-auth/providers/instagram"
|
||||
// import Keycloak from "next-auth/providers/keycloak"
|
||||
import Line from "next-auth/providers/line"
|
||||
import LinkedIn from "next-auth/providers/linkedin"
|
||||
import Mailchimp from "next-auth/providers/mailchimp"
|
||||
// import Okta from "next-auth/providers/okta"
|
||||
import Osu from "next-auth/providers/osu"
|
||||
import Patreon from "next-auth/providers/patreon"
|
||||
import Slack from "next-auth/providers/slack"
|
||||
import Spotify from "next-auth/providers/spotify"
|
||||
import Trakt from "next-auth/providers/trakt"
|
||||
import Twitch from "next-auth/providers/twitch"
|
||||
import Twitter from "next-auth/providers/twitter"
|
||||
import Vk from "next-auth/providers/vk"
|
||||
import Wikimedia from "next-auth/providers/wikimedia"
|
||||
import WorkOS from "next-auth/providers/workos"
|
||||
|
||||
// // Prisma
|
||||
// import { PrismaClient } from "@prisma/client"
|
||||
// import { PrismaAdapter } from "@next-auth/prisma-adapter"
|
||||
// const client = globalThis.prisma || new PrismaClient()
|
||||
// if (process.env.NODE_ENV !== "production") globalThis.prisma = client
|
||||
// const adapter = PrismaAdapter(client)
|
||||
|
||||
// // Fauna
|
||||
// import { Client as FaunaClient } from "faunadb"
|
||||
// import { FaunaAdapter } from "@next-auth/fauna-adapter"
|
||||
// const opts = { secret: process.env.FAUNA_SECRET, domain: process.env.FAUNA_DOMAIN }
|
||||
// const client = globalThis.fauna || new FaunaClient(opts)
|
||||
// if (process.env.NODE_ENV !== "production") globalThis.fauna = client
|
||||
// const adapter = FaunaAdapter(client)
|
||||
|
||||
// // TypeORM
|
||||
// import { TypeORMLegacyAdapter } from "@next-auth/typeorm-legacy-adapter"
|
||||
// const adapter = TypeORMLegacyAdapter({
|
||||
// type: "sqlite",
|
||||
// name: "next-auth-test-memory",
|
||||
// database: "./typeorm/dev.db",
|
||||
// synchronize: true,
|
||||
// })
|
||||
|
||||
// // Supabase
|
||||
// import { SupabaseAdapter } from "@next-auth/supabase-adapter"
|
||||
// const adapter = SupabaseAdapter({
|
||||
// url: process.env.NEXT_PUBLIC_SUPABASE_URL,
|
||||
// secret: process.env.SUPABASE_SERVICE_ROLE_KEY,
|
||||
// })
|
||||
|
||||
export const authOptions: NextAuthOptions = {
|
||||
// adapter,
|
||||
// debug: process.env.NODE_ENV !== "production",
|
||||
theme: {
|
||||
logo: "https://next-auth.js.org/img/logo/logo-sm.png",
|
||||
brandColor: "#1786fb",
|
||||
},
|
||||
providers: [
|
||||
Credentials({
|
||||
credentials: { password: { label: "Password", type: "password" } },
|
||||
async authorize(credentials) {
|
||||
if (credentials.password !== "pw") return null
|
||||
return {
|
||||
name: "Fill Murray",
|
||||
email: "bill@fillmurray.com",
|
||||
image: "https://www.fillmurray.com/64/64",
|
||||
id: "1",
|
||||
foo: "",
|
||||
}
|
||||
},
|
||||
}),
|
||||
Apple({
|
||||
clientId: process.env.APPLE_ID,
|
||||
clientSecret: process.env.APPLE_SECRET,
|
||||
}),
|
||||
Auth0({
|
||||
clientId: process.env.AUTH0_ID,
|
||||
clientSecret: process.env.AUTH0_SECRET,
|
||||
issuer: process.env.AUTH0_ISSUER,
|
||||
}),
|
||||
AzureAD({
|
||||
clientId: process.env.AZURE_AD_CLIENT_ID,
|
||||
clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
|
||||
tenantId: process.env.AZURE_AD_TENANT_ID,
|
||||
}),
|
||||
AzureB2C({
|
||||
clientId: process.env.AZURE_B2C_ID,
|
||||
clientSecret: process.env.AZURE_B2C_SECRET,
|
||||
issuer: process.env.AZURE_B2C_ISSUER,
|
||||
}),
|
||||
BoxyHQSAML({
|
||||
issuer: "https://jackson-demo.boxyhq.com",
|
||||
clientId: "tenant=boxyhq.com&product=saml-demo.boxyhq.com",
|
||||
clientSecret: "dummy",
|
||||
}),
|
||||
// Cognito({ clientId: process.env.COGNITO_ID, clientSecret: process.env.COGNITO_SECRET, issuer: process.env.COGNITO_ISSUER }),
|
||||
Discord({
|
||||
clientId: process.env.DISCORD_ID,
|
||||
clientSecret: process.env.DISCORD_SECRET,
|
||||
}),
|
||||
DuendeIDS6({
|
||||
clientId: "interactive.confidential",
|
||||
clientSecret: "secret",
|
||||
issuer: "https://demo.duendesoftware.com",
|
||||
}),
|
||||
Facebook({
|
||||
clientId: process.env.FACEBOOK_ID,
|
||||
clientSecret: process.env.FACEBOOK_SECRET,
|
||||
}),
|
||||
Foursquare({
|
||||
clientId: process.env.FOURSQUARE_ID,
|
||||
clientSecret: process.env.FOURSQUARE_SECRET,
|
||||
}),
|
||||
Freshbooks({
|
||||
clientId: process.env.FRESHBOOKS_ID,
|
||||
clientSecret: process.env.FRESHBOOKS_SECRET,
|
||||
}),
|
||||
GitHub({
|
||||
clientId: process.env.GITHUB_ID,
|
||||
clientSecret: process.env.GITHUB_SECRET,
|
||||
}),
|
||||
Gitlab({
|
||||
clientId: process.env.GITLAB_ID,
|
||||
clientSecret: process.env.GITLAB_SECRET,
|
||||
}),
|
||||
Google({
|
||||
clientId: process.env.GOOGLE_ID,
|
||||
clientSecret: process.env.GOOGLE_SECRET,
|
||||
}),
|
||||
// IDS4({ clientId: process.env.IDS4_ID, clientSecret: process.env.IDS4_SECRET, issuer: process.env.IDS4_ISSUER }),
|
||||
Instagram({
|
||||
clientId: process.env.INSTAGRAM_ID,
|
||||
clientSecret: process.env.INSTAGRAM_SECRET,
|
||||
}),
|
||||
// Keycloak({ clientId: process.env.KEYCLOAK_ID, clientSecret: process.env.KEYCLOAK_SECRET, issuer: process.env.KEYCLOAK_ISSUER }),
|
||||
Line({
|
||||
clientId: process.env.LINE_ID,
|
||||
clientSecret: process.env.LINE_SECRET,
|
||||
}),
|
||||
LinkedIn({
|
||||
clientId: process.env.LINKEDIN_ID,
|
||||
clientSecret: process.env.LINKEDIN_SECRET,
|
||||
}),
|
||||
Mailchimp({
|
||||
clientId: process.env.MAILCHIMP_ID,
|
||||
clientSecret: process.env.MAILCHIMP_SECRET,
|
||||
}),
|
||||
// Okta({ clientId: process.env.OKTA_ID, clientSecret: process.env.OKTA_SECRET, issuer: process.env.OKTA_ISSUER }),
|
||||
Osu({
|
||||
clientId: process.env.OSU_CLIENT_ID,
|
||||
clientSecret: process.env.OSU_CLIENT_SECRET,
|
||||
}),
|
||||
Patreon({
|
||||
clientId: process.env.PATREON_ID,
|
||||
clientSecret: process.env.PATREON_SECRET,
|
||||
}),
|
||||
Slack({
|
||||
clientId: process.env.SLACK_ID,
|
||||
clientSecret: process.env.SLACK_SECRET,
|
||||
}),
|
||||
Spotify({
|
||||
clientId: process.env.SPOTIFY_ID,
|
||||
clientSecret: process.env.SPOTIFY_SECRET,
|
||||
}),
|
||||
Trakt({
|
||||
clientId: process.env.TRAKT_ID,
|
||||
clientSecret: process.env.TRAKT_SECRET,
|
||||
}),
|
||||
Twitch({
|
||||
clientId: process.env.TWITCH_ID,
|
||||
clientSecret: process.env.TWITCH_SECRET,
|
||||
}),
|
||||
Twitter({
|
||||
clientId: process.env.TWITTER_ID,
|
||||
clientSecret: process.env.TWITTER_SECRET,
|
||||
}),
|
||||
// TwitterLegacy({ clientId: process.env.TWITTER_LEGACY_ID, clientSecret: process.env.TWITTER_LEGACY_SECRET }),
|
||||
Vk({ clientId: process.env.VK_ID, clientSecret: process.env.VK_SECRET }),
|
||||
Wikimedia({
|
||||
clientId: process.env.WIKIMEDIA_ID,
|
||||
clientSecret: process.env.WIKIMEDIA_SECRET,
|
||||
}),
|
||||
WorkOS({
|
||||
clientId: process.env.WORKOS_ID,
|
||||
clientSecret: process.env.WORKOS_SECRET,
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
||||
/**
|
||||
* Advanced Initialization - route handler
|
||||
*/
|
||||
// const handler = async (
|
||||
// req: NextRequest,
|
||||
// routeContext: { params: { nextauth: string[] } }
|
||||
// ): Promise<any> => {
|
||||
// return NextAuth(req, routeContext, authOptions)
|
||||
// }
|
||||
|
||||
const handler = NextAuth(authOptions)
|
||||
export { handler as GET, handler as POST }
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
|
||||
export default async function Page() {
|
||||
const session = await getServerSession()
|
||||
const session = await unstable_getServerSession()
|
||||
return <pre>{JSON.stringify(session, null, 2)}</pre>
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ export default function Footer() {
|
||||
<hr />
|
||||
<ul className={styles.navItems}>
|
||||
<li className={styles.navItem}>
|
||||
<a href="https://next-auth.js.org">Documentation</a>
|
||||
<a href="https://authjs.dev">Documentation</a>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<a href="https://www.npmjs.com/package/next-auth">NPM</a>
|
||||
<a href="https://www.npmjs.com/package/@auth/core">NPM</a>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<a href="https://github.com/nextauthjs/next-auth-example">GitHub</a>
|
||||
|
||||
1
apps/dev/next-env.d.ts
vendored
1
apps/dev/next-env.d.ts
vendored
@@ -1,6 +1,5 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
"scripts": {
|
||||
"clean": "rm -rf .next",
|
||||
"dev": "next dev",
|
||||
"lint": "next lint",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"email": "fake-smtp-server",
|
||||
@@ -21,15 +20,16 @@
|
||||
"@prisma/client": "^3",
|
||||
"@supabase/supabase-js": "^2.0.5",
|
||||
"faunadb": "^4",
|
||||
"next": "13.4.12",
|
||||
"next": "13.0.6",
|
||||
"next-auth": "workspace:*",
|
||||
"@auth/core": "workspace:*",
|
||||
"nodemailer": "^6",
|
||||
"react": "^18",
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jsonwebtoken": "^8.5.5",
|
||||
"@types/react": "^18.0.37",
|
||||
"@types/react": "^18.0.15",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"fake-smtp-server": "^0.8.0",
|
||||
"pg": "^8.7.3",
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
import NextAuth, { NextAuthOptions } from "next-auth"
|
||||
import { Auth, type AuthConfig } from "@auth/core"
|
||||
|
||||
// Providers
|
||||
import Apple from "next-auth/providers/apple"
|
||||
import Auth0 from "next-auth/providers/auth0"
|
||||
import AzureAD from "next-auth/providers/azure-ad"
|
||||
import AzureB2C from "next-auth/providers/azure-ad-b2c"
|
||||
import BoxyHQSAML from "next-auth/providers/boxyhq-saml"
|
||||
// import Cognito from "next-auth/providers/cognito"
|
||||
import Credentials from "next-auth/providers/credentials"
|
||||
import Discord from "next-auth/providers/discord"
|
||||
import DuendeIDS6 from "next-auth/providers/duende-identity-server6"
|
||||
// import Email from "next-auth/providers/email"
|
||||
import Facebook from "next-auth/providers/facebook"
|
||||
import Foursquare from "next-auth/providers/foursquare"
|
||||
import Freshbooks from "next-auth/providers/freshbooks"
|
||||
import GitHub from "next-auth/providers/github"
|
||||
import Gitlab from "next-auth/providers/gitlab"
|
||||
import Google from "next-auth/providers/google"
|
||||
// import IDS4 from "next-auth/providers/identity-server4"
|
||||
import Instagram from "next-auth/providers/instagram"
|
||||
// import Keycloak from "next-auth/providers/keycloak"
|
||||
import Line from "next-auth/providers/line"
|
||||
import LinkedIn from "next-auth/providers/linkedin"
|
||||
import Mailchimp from "next-auth/providers/mailchimp"
|
||||
// import Okta from "next-auth/providers/okta"
|
||||
import Osu from "next-auth/providers/osu"
|
||||
import Patreon from "next-auth/providers/patreon"
|
||||
import Slack from "next-auth/providers/slack"
|
||||
import Spotify from "next-auth/providers/spotify"
|
||||
import Trakt from "next-auth/providers/trakt"
|
||||
import Twitch from "next-auth/providers/twitch"
|
||||
import Twitter from "next-auth/providers/twitter"
|
||||
import Vk from "next-auth/providers/vk"
|
||||
import Wikimedia from "next-auth/providers/wikimedia"
|
||||
import WorkOS from "next-auth/providers/workos"
|
||||
import Apple from "@auth/core/providers/apple"
|
||||
import Auth0 from "@auth/core/providers/auth0"
|
||||
import AzureAD from "@auth/core/providers/azure-ad"
|
||||
import AzureB2C from "@auth/core/providers/azure-ad-b2c"
|
||||
import BoxyHQSAML from "@auth/core/providers/boxyhq-saml"
|
||||
// import Cognito from "@auth/core/providers/cognito"
|
||||
import Credentials from "@auth/core/providers/credentials"
|
||||
import Discord from "@auth/core/providers/discord"
|
||||
import DuendeIDS6 from "@auth/core/providers/duende-identity-server6"
|
||||
// import Email from "@auth/core/providers/email"
|
||||
import Facebook from "@auth/core/providers/facebook"
|
||||
import Foursquare from "@auth/core/providers/foursquare"
|
||||
import Freshbooks from "@auth/core/providers/freshbooks"
|
||||
import GitHub from "@auth/core/providers/github"
|
||||
import Gitlab from "@auth/core/providers/gitlab"
|
||||
import Google from "@auth/core/providers/google"
|
||||
// import IDS4 from "@auth/core/providers/identity-server4"
|
||||
import Instagram from "@auth/core/providers/instagram"
|
||||
// import Keycloak from "@auth/core/providers/keycloak"
|
||||
import Line from "@auth/core/providers/line"
|
||||
import LinkedIn from "@auth/core/providers/linkedin"
|
||||
import Mailchimp from "@auth/core/providers/mailchimp"
|
||||
// import Okta from "@auth/core/providers/okta"
|
||||
import Osu from "@auth/core/providers/osu"
|
||||
import Patreon from "@auth/core/providers/patreon"
|
||||
import Slack from "@auth/core/providers/slack"
|
||||
import Spotify from "@auth/core/providers/spotify"
|
||||
import Trakt from "@auth/core/providers/trakt"
|
||||
import Twitch from "@auth/core/providers/twitch"
|
||||
import Twitter from "@auth/core/providers/twitter"
|
||||
import Vk from "@auth/core/providers/vk"
|
||||
import Wikimedia from "@auth/core/providers/wikimedia"
|
||||
import WorkOS from "@auth/core/providers/workos"
|
||||
|
||||
// // Prisma
|
||||
// import { PrismaClient } from "@prisma/client"
|
||||
@@ -66,7 +66,7 @@ import WorkOS from "next-auth/providers/workos"
|
||||
// secret: process.env.SUPABASE_SERVICE_ROLE_KEY,
|
||||
// })
|
||||
|
||||
export const authOptions: NextAuthOptions = {
|
||||
export const authConfig: AuthConfig = {
|
||||
// adapter,
|
||||
// debug: process.env.NODE_ENV !== "production",
|
||||
theme: {
|
||||
@@ -118,9 +118,10 @@ export const authOptions: NextAuthOptions = {
|
||||
Wikimedia({ clientId: process.env.WIKIMEDIA_ID, clientSecret: process.env.WIKIMEDIA_SECRET }),
|
||||
WorkOS({ clientId: process.env.WORKOS_ID, clientSecret: process.env.WORKOS_SECRET }),
|
||||
],
|
||||
// debug: process.env.NODE_ENV !== "production",
|
||||
}
|
||||
|
||||
if (authOptions.adapter) {
|
||||
if (authConfig.adapter) {
|
||||
// TODO:
|
||||
// authOptions.providers.unshift(
|
||||
// // NOTE: You can start a fake e-mail server with `pnpm email`
|
||||
@@ -129,4 +130,22 @@ if (authOptions.adapter) {
|
||||
// )
|
||||
}
|
||||
|
||||
export default NextAuth(authOptions)
|
||||
// TODO: move to next-auth/edge
|
||||
function AuthHandler(...args: any[]) {
|
||||
const envSecret = process.env.AUTH_SECRET ?? process.env.NEXTAUTH_SECRET
|
||||
const envTrustHost = !!(process.env.NEXTAUTH_URL ?? process.env.AUTH_TRUST_HOST ?? process.env.VERCEL ?? process.env.NODE_ENV !== "production")
|
||||
if (args.length === 1) {
|
||||
return async (req: Request) => {
|
||||
args[0].secret ??= envSecret
|
||||
args[0].trustHost ??= envTrustHost
|
||||
return Auth(req, args[0])
|
||||
}
|
||||
}
|
||||
args[1].secret ??= envSecret
|
||||
args[1].trustHost ??= envTrustHost
|
||||
return Auth(args[0], args[1])
|
||||
}
|
||||
|
||||
export default AuthHandler(authConfig)
|
||||
|
||||
export const config = { runtime: "experimental-edge" }
|
||||
@@ -1,9 +1,9 @@
|
||||
// This is an example of to protect an API route
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "../auth/[...nextauth]"
|
||||
|
||||
export default async (req, res) => {
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
|
||||
if (session) {
|
||||
res.send({
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// This is an example of how to access a session from an API route
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "../auth/[...nextauth]"
|
||||
|
||||
export default async (req, res) => {
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
res.json(session)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// This is an example of how to query data from Supabase with RLS.
|
||||
// Learn more about Row Levele Security (RLS): https://supabase.com/docs/guides/auth/row-level-security
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "../auth/[...nextauth]"
|
||||
import { createClient } from "@supabase/supabase-js"
|
||||
|
||||
export default async (req, res) => {
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
|
||||
if (!session)
|
||||
return res.send(JSON.stringify({ error: "No session!" }, null, 2))
|
||||
|
||||
@@ -5,7 +5,8 @@ export default function Page () {
|
||||
<Layout>
|
||||
<h1>NextAuth.js Example</h1>
|
||||
<p>
|
||||
This is an example site to demonstrate how to use <a href='https://next-auth.js.org'>NextAuth.js</a> for authentication.
|
||||
This is an example site to demonstrate how to use{' '}
|
||||
<a href="https://authjs.dev">NextAuth.js</a> for authentication.
|
||||
</p>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
import Layout from '../components/layout'
|
||||
import Layout from "../components/layout"
|
||||
|
||||
export default function Page () {
|
||||
export default function Page() {
|
||||
return (
|
||||
<Layout>
|
||||
<p>
|
||||
This is an example site to demonstrate how to use <a href='https://next-auth.js.org'>NextAuth.js</a> for authentication.
|
||||
This is an example site to demonstrate how to use{" "}
|
||||
<a href="https://authjs.dev">Auth.js</a> for authentication.
|
||||
</p>
|
||||
<h2>Terms of Service</h2>
|
||||
<p>
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</p>
|
||||
<h2>Privacy Policy</h2>
|
||||
<p>
|
||||
This site uses JSON Web Tokens and an in-memory database which resets every ~2 hours.
|
||||
This site uses JSON Web Tokens and an in-memory database which resets
|
||||
every ~2 hours.
|
||||
</p>
|
||||
<p>
|
||||
Data provided to this site is exclusively used to support signing in
|
||||
and is not passed to any third party services, other than via SMTP or OAuth for the
|
||||
purposes of authentication.
|
||||
Data provided to this site is exclusively used to support signing in and
|
||||
is not passed to any third party services, other than via SMTP or OAuth
|
||||
for the purposes of authentication.
|
||||
</p>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This is an example of how to protect content using server rendering
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "./api/auth/[...nextauth]"
|
||||
import Layout from "../components/layout"
|
||||
import AccessDenied from "../components/access-denied"
|
||||
@@ -26,7 +26,11 @@ export default function Page({ content, session }) {
|
||||
}
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
const session = await getServerSession(context.req, context.res, authOptions)
|
||||
const session = await unstable_getServerSession(
|
||||
context.req,
|
||||
context.res,
|
||||
authOptions
|
||||
)
|
||||
let content = null
|
||||
|
||||
if (session) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import Layout from "../components/layout"
|
||||
import { authOptions } from "./api/auth/[...nextauth]"
|
||||
import { authOptions } from './api/auth/[...nextauth]';
|
||||
|
||||
export default function Page() {
|
||||
// As this page uses Server Side Rendering, the `session` will be already
|
||||
@@ -12,11 +12,11 @@ export default function Page() {
|
||||
<Layout>
|
||||
<h1>Server Side Rendering</h1>
|
||||
<p>
|
||||
This page uses the <strong>getServerSession()</strong> method in{" "}
|
||||
<strong>getServerSideProps()</strong>.
|
||||
This page uses the <strong>unstable_getServerSession()</strong> method
|
||||
in <strong>getServerSideProps()</strong>.
|
||||
</p>
|
||||
<p>
|
||||
Using <strong>getServerSession()</strong> in{" "}
|
||||
Using <strong>unstable_getServerSession()</strong> in{" "}
|
||||
<strong>getServerSideProps()</strong> is currently the recommended
|
||||
approach, although the API may still change, if you need to support
|
||||
Server Side Rendering with authentication.
|
||||
@@ -40,7 +40,11 @@ export default function Page() {
|
||||
export async function getServerSideProps(context) {
|
||||
return {
|
||||
props: {
|
||||
session: await getServerSession(context.req, context.res, authOptions),
|
||||
session: await unstable_getServerSession(
|
||||
context.req,
|
||||
context.res,
|
||||
authOptions
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ export default function Page() {
|
||||
|
||||
useEffect(() => {
|
||||
if (session) {
|
||||
console.log(session)
|
||||
// User is logged in, let's fetch their data.
|
||||
const { supabaseAccessToken } = session
|
||||
const supabase = createClient(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This is an example of how to protect content using server rendering
|
||||
// and fetching data from Supabase with RLS enabled.
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "./api/auth/[...nextauth]"
|
||||
import { createClient } from "@supabase/supabase-js"
|
||||
import Layout from "../components/layout"
|
||||
@@ -27,7 +27,11 @@ export default function Page({ data, session }) {
|
||||
}
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
const session = await getServerSession(context.req, context.res, authOptions)
|
||||
const session = await unstable_getServerSession(
|
||||
context.req,
|
||||
context.res,
|
||||
authOptions
|
||||
)
|
||||
|
||||
if (!session)
|
||||
return {
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"strictNullChecks": true
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
> The example repository is maintained from a [monorepo](https://github.com/nextauthjs/next-auth/tree/main/apps/example-gatsby). Pull Requests should be opened against [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth).
|
||||
|
||||
<p align="center">
|
||||
<br/>
|
||||
<a href="https://next-auth.js.org" target="_blank"><img width="150px" src="https://next-auth.js.org/img/logo/logo-sm.png" /></a>
|
||||
<h3 align="center">NextAuth.js Example App</h3>
|
||||
<p align="center">
|
||||
Open Source. Full Stack. Own Your Data.
|
||||
</p>
|
||||
<p align="center" style="align: center;">
|
||||
<a href="https://npm.im/next-auth">
|
||||
<img alt="npm" src="https://img.shields.io/npm/v/next-auth?color=green&label=next-auth">
|
||||
</a>
|
||||
<a href="https://bundlephobia.com/result?p=next-auth-example">
|
||||
<img src="https://img.shields.io/bundlephobia/minzip/next-auth?label=next-auth" alt="Bundle Size"/>
|
||||
</a>
|
||||
<a href="https://www.npmtrends.com/next-auth">
|
||||
<img src="https://img.shields.io/npm/dm/next-auth?label=next-auth%20downloads" alt="Downloads" />
|
||||
</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
## Overview
|
||||
|
||||
NextAuth.js is a complete open source authentication solution.
|
||||
|
||||
This is an example application that shows how `next-auth` is applied to a basic Gatsby app. We are showing how to configure the backend both as a [Vercel Function](https://vercel.com/docs/concepts/functions/introduction) for deployment to Vercel, and also for [Gatsby Functions](https://www.gatsbyjs.com/docs/reference/functions) for other platforms.
|
||||
|
||||
The deployed version can be found at [`next-auth-gatsby-example.vercel.app`](https://next-auth-gatsby-example.vercel.app)
|
||||
|
||||
### About NextAuth.js
|
||||
|
||||
NextAuth.js is an easy to implement, full-stack (client/server) open source authentication library originally designed for [Next.js](https://nextjs.org) and [Serverless](https://vercel.com), but this example shows how to use it in a Gatsby project. Our goal is to [support even more frameworks](https://github.com/nextauthjs/next-auth/issues/2294) in the future.
|
||||
|
||||
Go to [next-auth.js.org](https://next-auth.js.org) for more information and documentation.
|
||||
|
||||
> *NextAuth.js is not officially associated with Vercel or Next.js.*
|
||||
|
||||
## Getting Started
|
||||
|
||||
### 1. Clone the repository and install dependencies
|
||||
|
||||
```
|
||||
git clone https://github.com/nextauthjs/next-auth-gatsby-example.git
|
||||
cd next-auth-gatsby-example
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. Configure 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 one or more providers (e.g. Google, Twitter, GitHub, Email, etc).
|
||||
|
||||
#### Database
|
||||
|
||||
A database is needed to persist user accounts and to support email sign in. However, you can still use NextAuth.js for authentication without a database by using OAuth for authentication. If you do not specify a database, [JSON Web Tokens](https://jwt.io/introduction) will be enabled by default.
|
||||
|
||||
You **can** skip configuring a database and come back to it later if you want.
|
||||
|
||||
For more information about setting up a database, please check out the following links:
|
||||
|
||||
* Docs: [next-auth.js.org/adapters/overview](https://next-auth.js.org/adapters/overview)
|
||||
|
||||
### 3. Configure Authentication Providers
|
||||
|
||||
1. Review and update options in `nextauth.config.js` as needed.
|
||||
|
||||
2. When setting up OAuth, in the developer admin page for each of your OAuth services, you should configure the callback URL to use a callback path of `{server}/api/auth/callback/{provider}`.
|
||||
|
||||
e.g. For Google OAuth you would use: `http://localhost:3000/api/auth/callback/google`
|
||||
|
||||
A list of configured providers and their callback URLs is available from the endpoint `/api/auth/providers`. You can find more information at https://next-auth.js.org/configuration/providers/oauth
|
||||
|
||||
3. You can also choose to specify an SMTP server for passwordless sign in via email.
|
||||
|
||||
### 4. Start the application
|
||||
|
||||
To run your site locally, use:
|
||||
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
|
||||
To run it in production mode, use:
|
||||
|
||||
```
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
### 5. Preparing for Production
|
||||
|
||||
Follow the [Deployment documentation](https://next-auth.js.org/deployment)
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
<a href="https://vercel.com?utm_source=nextauthjs&utm_campaign=oss">
|
||||
<img width="170px" src="https://raw.githubusercontent.com/nextauthjs/next-auth/canary/www/static/img/powered-by-vercel.svg" alt="Powered By Vercel" />
|
||||
</a>
|
||||
<p align="left">Thanks to Vercel sponsoring this project by allowing it to be deployed for free for the entire NextAuth.js Team</p>
|
||||
|
||||
## License
|
||||
|
||||
ISC
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
</p>
|
||||
<p align="center" style="align: center;">
|
||||
<a href="https://npm.im/next-auth">
|
||||
<img alt="npm" src="https://img.shields.io/npm/v/next-auth?color=green&label=next-auth">
|
||||
<img alt="npm" src="https://img.shields.io/npm/v/next-auth?color=green&label=next-auth&style=flat-square">
|
||||
</a>
|
||||
<a href="https://bundlephobia.com/result?p=next-auth-example">
|
||||
<img src="https://img.shields.io/bundlephobia/minzip/next-auth?label=next-auth" alt="Bundle Size"/>
|
||||
<img src="https://img.shields.io/bundlephobia/minzip/next-auth?label=size&style=flat-square" alt="Bundle Size"/>
|
||||
</a>
|
||||
<a href="https://www.npmtrends.com/next-auth">
|
||||
<img src="https://img.shields.io/npm/dm/next-auth?label=next-auth%20downloads" alt="Downloads" />
|
||||
<img src="https://img.shields.io/npm/dm/next-auth?label=downloads&style=flat-square" alt="Downloads" />
|
||||
</a>
|
||||
<a href="https://npm.im/next-auth">
|
||||
<img src="https://img.shields.io/badge/npm-TypeScript-blue" alt="TypeScript" />
|
||||
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
|
||||
</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^17",
|
||||
"@types/react": "^18.0.37",
|
||||
"@types/react": "^18.0.15",
|
||||
"typescript": "^4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ export const authOptions: NextAuthOptions = {
|
||||
],
|
||||
theme: {
|
||||
colorScheme: "light",
|
||||
logo: "https://next-auth.js.org/img/logo/logo-sm.png",
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token }) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This is an example of to protect an API route
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "../auth/[...nextauth]"
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
@@ -8,7 +8,7 @@ export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
|
||||
if (session) {
|
||||
return res.send({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This is an example of how to access a session from an API route
|
||||
import { getServerSession } from "next-auth"
|
||||
import { unstable_getServerSession } from "next-auth"
|
||||
import { authOptions } from "../auth/[...nextauth]"
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
@@ -8,6 +8,6 @@ export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
res.send(JSON.stringify(session, null, 2))
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "./api/auth/[...nextauth]"
|
||||
import Layout from "../components/layout"
|
||||
|
||||
@@ -12,11 +12,11 @@ export default function ServerSidePage({ session }: { session: Session }) {
|
||||
<Layout>
|
||||
<h1>Server Side Rendering</h1>
|
||||
<p>
|
||||
This page uses the <strong>getServerSession()</strong> method in{" "}
|
||||
<strong>getServerSideProps()</strong>.
|
||||
This page uses the <strong>unstable_getServerSession()</strong> method
|
||||
in <strong>getServerSideProps()</strong>.
|
||||
</p>
|
||||
<p>
|
||||
Using <strong>getServerSession()</strong> in{" "}
|
||||
Using <strong>unstable_getServerSession()</strong> in{" "}
|
||||
<strong>getServerSideProps()</strong> is the recommended approach if you
|
||||
need to support Server Side Rendering with authentication.
|
||||
</p>
|
||||
@@ -37,7 +37,11 @@ export default function ServerSidePage({ session }: { session: Session }) {
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
return {
|
||||
props: {
|
||||
session: await getServerSession(context.req, context.res, authOptions),
|
||||
session: await unstable_getServerSession(
|
||||
context.req,
|
||||
context.res,
|
||||
authOptions
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
5
apps/example-sveltekit/.env.example
Normal file
5
apps/example-sveltekit/.env.example
Normal file
@@ -0,0 +1,5 @@
|
||||
GITHUB_ID=
|
||||
GITHUB_SECRET=
|
||||
# On UNIX systems you can use `openssl rand -hex 32` or
|
||||
# https://generate-secret.vercel.app/32 to generate a secret.
|
||||
AUTH_SECRET=
|
||||
13
apps/example-sveltekit/.eslintignore
Normal file
13
apps/example-sveltekit/.eslintignore
Normal file
@@ -0,0 +1,13 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
20
apps/example-sveltekit/.eslintrc.cjs
Normal file
20
apps/example-sveltekit/.eslintrc.cjs
Normal file
@@ -0,0 +1,20 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
|
||||
plugins: ['svelte3', '@typescript-eslint'],
|
||||
ignorePatterns: ['*.cjs'],
|
||||
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
||||
settings: {
|
||||
'svelte3/typescript': () => require('typescript')
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
node: true
|
||||
}
|
||||
};
|
||||
12
apps/example-sveltekit/.gitignore
vendored
Normal file
12
apps/example-sveltekit/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
.vercel
|
||||
.output
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
13
apps/example-sveltekit/.prettierignore
Normal file
13
apps/example-sveltekit/.prettierignore
Normal file
@@ -0,0 +1,13 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
6
apps/example-sveltekit/.prettierrc
Normal file
6
apps/example-sveltekit/.prettierrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"semi": false,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"pluginSearchDirs": ["."],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
||||
28
apps/example-sveltekit/README.md
Normal file
28
apps/example-sveltekit/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
> The example repository is maintained from a [monorepo](https://github.com/nextauthjs/next-auth/tree/main/apps/example-sveltekit). Pull Requests should be opened against [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth).
|
||||
|
||||
<p align="center">
|
||||
<br/>
|
||||
<a href="https://authjs.dev" target="_blank"><img width="150px" src="https://authjs.dev/img/logo/logo-sm.png" /></a>
|
||||
<h3 align="center">Auth.js Example App with <a href="https://kit.svelte.dev">SvelteKit</a></h3>
|
||||
<p align="center">
|
||||
Open Source. Full Stack. Own Your Data.
|
||||
</p>
|
||||
<p align="center" style="align: center;">
|
||||
<a href="https://npm.im/@auth/sveltekit">
|
||||
<img alt="npm" src="https://img.shields.io/npm/v/@auth/sveltekit?color=green&label=@auth/sveltekit&style=flat-square">
|
||||
</a>
|
||||
<a href="https://bundlephobia.com/result?p=sveltekit-auth-example">
|
||||
<img src="https://img.shields.io/bundlephobia/minzip/@auth/sveltekit?label=size&style=flat-square" alt="Bundle Size"/>
|
||||
</a>
|
||||
<a href="https://www.npmtrends.com/@auth/sveltekit">
|
||||
<img src="https://img.shields.io/npm/dm/@auth/sveltekit?label=%20downloads&style=flat-square" alt="Downloads" />
|
||||
</a>
|
||||
<a href="https://npm.im/next-auth">
|
||||
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
|
||||
</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
# Documentation
|
||||
|
||||
- [sveltekit.authjs.dev](https://sveltekit.authjs.dev)
|
||||
22
apps/example-sveltekit/package.json
Normal file
22
apps/example-sveltekit/package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "next",
|
||||
"@sveltejs/kit": "next",
|
||||
"svelte": "3.55.0",
|
||||
"svelte-check": "2.10.2",
|
||||
"typescript": "4.9.4",
|
||||
"vite": "4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/core": "latest",
|
||||
"@auth/sveltekit": "latest"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
1
apps/example-sveltekit/src/app.d.ts
vendored
Normal file
1
apps/example-sveltekit/src/app.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="@auth/sveltekit" />
|
||||
13
apps/example-sveltekit/src/app.html
Normal file
13
apps/example-sveltekit/src/app.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
7
apps/example-sveltekit/src/hooks.server.ts
Normal file
7
apps/example-sveltekit/src/hooks.server.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import SvelteKitAuth from "@auth/sveltekit"
|
||||
import GitHub from "@auth/core/providers/github"
|
||||
import { GITHUB_ID, GITHUB_SECRET } from "$env/static/private"
|
||||
|
||||
export const handle = SvelteKitAuth({
|
||||
providers: [GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET })],
|
||||
})
|
||||
12
apps/example-sveltekit/src/lib/SignInButton.svelte
Normal file
12
apps/example-sveltekit/src/lib/SignInButton.svelte
Normal file
@@ -0,0 +1,12 @@
|
||||
<script lang="ts">
|
||||
export let provider: any
|
||||
</script>
|
||||
|
||||
<form action={provider.signinUrl} method="POST">
|
||||
{#if provider.callbackUrl}
|
||||
<input type="hidden" name="callbackUrl" value={provider.callbackUrl} />
|
||||
{/if}
|
||||
<button type="submit" class="button">
|
||||
<slot>Sign in with {provider.name}</slot>
|
||||
</button>
|
||||
</form>
|
||||
7
apps/example-sveltekit/src/routes/+layout.server.ts
Normal file
7
apps/example-sveltekit/src/routes/+layout.server.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { LayoutServerLoad } from "./$types"
|
||||
|
||||
export const load: LayoutServerLoad = async (event) => {
|
||||
return {
|
||||
session: await event.locals.getSession(),
|
||||
}
|
||||
}
|
||||
151
apps/example-sveltekit/src/routes/+layout.svelte
Normal file
151
apps/example-sveltekit/src/routes/+layout.svelte
Normal file
@@ -0,0 +1,151 @@
|
||||
<script lang="ts">
|
||||
import { page } from "$app/stores"
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<header>
|
||||
<div class="signedInStatus">
|
||||
<p class="nojs-show loaded">
|
||||
{#if $page.data.session}
|
||||
{#if $page.data.session.user?.image}
|
||||
<span
|
||||
style="background-image: url('{$page.data.session.user.image}')"
|
||||
class="avatar"
|
||||
/>
|
||||
{/if}
|
||||
<span class="signedInText">
|
||||
<small>Signed in as</small><br />
|
||||
<strong
|
||||
>{$page.data.session.user?.email ??
|
||||
$page.data.session.user?.name}</strong
|
||||
>
|
||||
</span>
|
||||
<a href="/auth/signout" class="button">Sign out</a>
|
||||
{:else}
|
||||
<span class="notSignedInText">You are not signed in</span>
|
||||
<a href="/auth/signin" class="buttonPrimary">Sign in</a>
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
<nav>
|
||||
<ul class="navItems">
|
||||
<li class="navItem"><a href="/">Home</a></li>
|
||||
<li class="navItem"><a href="/protected">Protected</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:global(body) {
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
|
||||
"Noto Color Emoji";
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
:global(li),
|
||||
:global(p) {
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
:global(a) {
|
||||
font-weight: 500;
|
||||
}
|
||||
:global(hr) {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
:global(iframe) {
|
||||
background: #ccc;
|
||||
border: 1px solid #ccc;
|
||||
height: 10rem;
|
||||
width: 100%;
|
||||
border-radius: 0.5rem;
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
.nojs-show {
|
||||
opacity: 1;
|
||||
top: 0;
|
||||
}
|
||||
.signedInStatus {
|
||||
display: block;
|
||||
min-height: 4rem;
|
||||
width: 100%;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
7
apps/example-sveltekit/src/routes/+page.svelte
Normal file
7
apps/example-sveltekit/src/routes/+page.svelte
Normal file
@@ -0,0 +1,7 @@
|
||||
<h1>SvelteKit Auth Example</h1>
|
||||
<p>
|
||||
This is an example site to demonstrate how to use <a
|
||||
href="https://kit.svelte.dev/">SvelteKit</a
|
||||
>
|
||||
with <a href="https://sveltekit.authjs.dev">SvelteKit Auth</a> for authentication.
|
||||
</p>
|
||||
10
apps/example-sveltekit/src/routes/protected/+page.svelte
Normal file
10
apps/example-sveltekit/src/routes/protected/+page.svelte
Normal file
@@ -0,0 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { page } from "$app/stores"
|
||||
</script>
|
||||
|
||||
<h1>Protected page</h1>
|
||||
<p>
|
||||
This is a protected content. You can access this content because you are
|
||||
signed in.
|
||||
</p>
|
||||
<p>Session expiry: {$page.data.session?.expires}</p>
|
||||
10
apps/example-sveltekit/src/routes/protected/+page.ts
Normal file
10
apps/example-sveltekit/src/routes/protected/+page.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { redirect } from "@sveltejs/kit"
|
||||
import type { PageLoad } from "./$types"
|
||||
|
||||
export const load: PageLoad = async ({ parent }) => {
|
||||
const { session } = await parent()
|
||||
if (!session?.user) {
|
||||
throw redirect(302, "/")
|
||||
}
|
||||
return {}
|
||||
}
|
||||
BIN
apps/example-sveltekit/static/favicon.ico
Normal file
BIN
apps/example-sveltekit/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
15
apps/example-sveltekit/svelte.config.js
Normal file
15
apps/example-sveltekit/svelte.config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import adapter from '@sveltejs/adapter-auto';
|
||||
import { vitePreprocess } from '@sveltejs/kit/vite';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
||||
// for more information about preprocessors
|
||||
preprocess: vitePreprocess(),
|
||||
|
||||
kit: {
|
||||
adapter: adapter()
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
17
apps/example-sveltekit/tsconfig.json
Normal file
17
apps/example-sveltekit/tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true
|
||||
}
|
||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
}
|
||||
8
apps/example-sveltekit/vite.config.js
Normal file
8
apps/example-sveltekit/vite.config.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { sveltekit } from "@sveltejs/kit/vite"
|
||||
|
||||
/** @type {import('vite').UserConfig} */
|
||||
const config = {
|
||||
plugins: [sveltekit()],
|
||||
}
|
||||
|
||||
export default config
|
||||
109
apps/playground-gatsby/README.md
Normal file
109
apps/playground-gatsby/README.md
Normal file
@@ -0,0 +1,109 @@
|
||||
> The example repository is maintained from a [monorepo](https://github.com/nextauthjs/next-auth/tree/main/apps/playground-gatsby). Pull Requests should be opened against [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth).
|
||||
|
||||
<p align="center">
|
||||
<br/>
|
||||
<a href="https://authjs.dev" target="_blank"><img width="150px" src="https://authjs.dev/img/logo/logo-sm.png" /></a>
|
||||
<h3 align="center">Auth.js Example App</h3>
|
||||
<p align="center">
|
||||
Open Source. Full Stack. Own Your Data.
|
||||
</p>
|
||||
<p align="center" style="align: center;">
|
||||
<a href="https://npm.im/next-auth">
|
||||
<img alt="npm" src="https://img.shields.io/npm/v/@auth/core?color=green&label=@auth/core&style=flat-square">
|
||||
</a>
|
||||
<a href="https://bundlephobia.com/result?p=@auth/core">
|
||||
<img src="https://img.shields.io/bundlephobia/minzip/@auth/core?label=bundle&style=flat-square" alt="Bundle Size"/>
|
||||
</a>
|
||||
<a href="https://www.npmtrends.com/@auth/core">
|
||||
<img src="https://img.shields.io/npm/dm/@auth/core?label=downloads&style=flat-square" alt="Downloads" />
|
||||
</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
## Overview
|
||||
|
||||
Auth.js is a complete open source authentication solution.
|
||||
|
||||
This is an example application that shows how `@auth/core` is applied to a basic Gatsby app. We are showing how to configure the backend both as a [Vercel Function](https://vercel.com/docs/concepts/functions/introduction) for deployment to Vercel, and also for [Gatsby Functions](https://www.gatsbyjs.com/docs/reference/functions) for other platforms.
|
||||
|
||||
The deployed version can be found at [`next-auth-gatsby-example.vercel.app`](https://next-auth-gatsby-example.vercel.app)
|
||||
|
||||
### About Auth.js
|
||||
|
||||
Auth.js is an easy to implement, full-stack (client/server) open source authentication library originally designed for [Next.js](https://nextjs.org) and [Serverless](https://vercel.com), but this example shows how to use it in a Gatsby project. Our goal is to [support even more frameworks](https://github.com/nextauthjs/next-auth/issues/2294) in the future.
|
||||
|
||||
Go to [authjs.dev](https://authjs.dev) for more information and documentation.
|
||||
|
||||
> Auth.js is not officially associated with Vercel or Next.js._
|
||||
|
||||
## Getting Started
|
||||
|
||||
### 1. Clone the repository and install dependencies
|
||||
|
||||
```
|
||||
git clone https://github.com/nextauthjs/next-auth-gatsby-example.git
|
||||
cd next-auth-gatsby-example
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. Configure 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 one or more providers (e.g. Google, Twitter, GitHub, Email, etc).
|
||||
|
||||
#### Database
|
||||
|
||||
A database is needed to persist user accounts and to support email sign in. However, you can still use Auth.js for authentication without a database by using OAuth for authentication. If you do not specify a database, [JSON Web Tokens](https://jwt.io/introduction) will be enabled by default.
|
||||
|
||||
You **can** skip configuring a database and come back to it later if you want.
|
||||
|
||||
For more information about setting up a database, please check out the following links:
|
||||
|
||||
- Docs: [authjs.dev/reference/adapters/overview](https://authjs.dev/reference/adapters/overview)
|
||||
|
||||
### 3. Configure Authentication Providers
|
||||
|
||||
1. Review and update options in `nextauth.config.js` as needed.
|
||||
|
||||
2. When setting up OAuth, in the developer admin page for each of your OAuth services, you should configure the callback URL to use a callback path of `{server}/api/auth/callback/{provider}`.
|
||||
|
||||
e.g. For Google OAuth you would use: `http://localhost:3000/api/auth/callback/google`
|
||||
|
||||
A list of configured providers and their callback URLs is available from the endpoint `/api/auth/providers`. You can find more information at [authjs.dev/reference/providers/oauth-builtin](https://authjs.dev/reference/providers/oauth-builtin).
|
||||
|
||||
3. You can also choose to specify an SMTP server for passwordless sign in via email.
|
||||
|
||||
### 4. Start the application
|
||||
|
||||
To run your site locally, use:
|
||||
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
|
||||
To run it in production mode, use:
|
||||
|
||||
```
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
### 5. Preparing for Production
|
||||
|
||||
Follow the [Deployment documentation](https://authjs.dev/guides/basics/deployment)
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
<a href="https://vercel.com?utm_source=authjs&utm_campaign=oss">
|
||||
<img width="170px" src="https://powered-by-vercel.api.soraharu.com/powered-by-vercel.svg" alt="Powered By Vercel" />
|
||||
</a>
|
||||
<p align="left">Thanks to Vercel sponsoring this project by allowing it to be deployed for free for the entire Auth.js Team</p>
|
||||
|
||||
## License
|
||||
|
||||
ISC
|
||||
@@ -1,5 +1,5 @@
|
||||
// Gatsby Functions are not yet supported on Vercel, so you'll need to use the root `api` folder.
|
||||
import NextAuth from "next-auth/next"
|
||||
import NextAuth from "next-auth"
|
||||
import { authConfig } from "../../nextauth.config"
|
||||
|
||||
export default async function handler(req, res) {
|
||||
@@ -1,6 +1,6 @@
|
||||
// If your deployment environment supports Gatsby Functions, you won't need the root `api` folder, only this.
|
||||
|
||||
import NextAuth from "next-auth/next"
|
||||
import NextAuth from "next-auth"
|
||||
import { authConfig } from "../../nextauth.config"
|
||||
|
||||
export default async function handler(req, res) {
|
||||
@@ -11,8 +11,7 @@ export default function Home() {
|
||||
<h1>NextAuth.js Example</h1>
|
||||
<p>
|
||||
An example site to demonstrate how to use{" "}
|
||||
<a href="https://next-auth.js.org">NextAuth.js</a> for authentication in
|
||||
Gatsby.
|
||||
<a href="https://authjs.dev">Auth.js</a> for authentication in Gatsby.
|
||||
</p>
|
||||
{
|
||||
{
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -1,12 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1,4 +0,0 @@
|
||||
dist
|
||||
node_modules
|
||||
tsconfig.json
|
||||
package.json
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"@nuxtjs/eslint-config-typescript"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"off"
|
||||
]
|
||||
}
|
||||
}
|
||||
7
apps/playground-nuxt/.eslintrc.cjs
Normal file
7
apps/playground-nuxt/.eslintrc.cjs
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['@nuxt/eslint-config'],
|
||||
rules: {
|
||||
'vue/multi-word-component-names': 'off'
|
||||
}
|
||||
}
|
||||
52
apps/playground-nuxt/.gitignore
vendored
52
apps/playground-nuxt/.gitignore
vendored
@@ -1,52 +1,4 @@
|
||||
# Dependencies
|
||||
node_modules
|
||||
|
||||
# Logs
|
||||
*.log*
|
||||
|
||||
# Temp directories
|
||||
.temp
|
||||
.tmp
|
||||
.cache
|
||||
|
||||
# Yarn
|
||||
**/.yarn/cache
|
||||
**/.yarn/*state*
|
||||
|
||||
# Generated dirs
|
||||
dist
|
||||
|
||||
# Nuxt
|
||||
.nuxt
|
||||
.output
|
||||
.vercel_build_output
|
||||
.build-*
|
||||
.env
|
||||
.netlify
|
||||
|
||||
# Env
|
||||
.env
|
||||
|
||||
# Testing
|
||||
reports
|
||||
coverage
|
||||
*.lcov
|
||||
.nyc_output
|
||||
|
||||
# VSCode
|
||||
.vscode
|
||||
|
||||
# Intellij idea
|
||||
*.iml
|
||||
.idea
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
.vercel
|
||||
dist
|
||||
output
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
imports.autoImport=false
|
||||
@@ -1,21 +1,13 @@
|
||||
# NextAuth + Nuxt 3 Playground
|
||||
> The example repository is maintained from a [monorepo](https://github.com/nextauthjs/next-auth/tree/main/apps/playground-nuxt). Pull Requests should be opened against [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth).
|
||||
|
||||
NextAuth.js is committed to bringing easy authentication to other frameworks. [#2294](https://github.com/nextauthjs/next-auth/issues/2294)
|
||||
|
||||
Nuxt 3 support with NextAuth.js is currently experimental. This directory contains a minimal, proof-of-concept application. Parts of this is expected to be abstracted away into a package like` @next-auth/nuxt.`
|
||||
|
||||
This package uses Nuxt's [module starter](https://github.com/nuxt/starter/tree/module).
|
||||
|
||||
Demo: https://next-auth-nuxt-demo.vercel.app
|
||||
Nuxt 3 support with Auth.js is currently experimental. This directory contains a minimal, proof-of-concept application. Parts of this is expected to be abstracted away into a package like `@auth/nuxt`.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Add the module to the modules section of `nuxt.config.ts`:
|
||||
1. Setup your environment variables in `nuxt.config.ts`:
|
||||
|
||||
```ts
|
||||
export default defineNuxtConfig({
|
||||
// temporary module name.
|
||||
modules: ['next-auth-nuxt'],
|
||||
// https://v3.nuxtjs.org/migration/runtime-config#runtime-config
|
||||
runtimeConfig: {
|
||||
secret: process.env.NEXTAUTH_SECRET
|
||||
@@ -23,86 +15,36 @@ export default defineNuxtConfig({
|
||||
clientId: process.env.GITHUB_CLIENT_ID,
|
||||
clientSecret: process.env.GITHUB_CLIENT_SECRET
|
||||
}
|
||||
},
|
||||
// https://v3.nuxtjs.org/guide/concepts/esm#aliasing-libraries
|
||||
// Fix for GithubProvider (or whichever provider you choose) is not a function error in Vite
|
||||
alias: {
|
||||
'next-auth/providers/github': 'node_modules/next-auth/providers/github.js'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Add API route
|
||||
2. Set up Auth.js options
|
||||
|
||||
To add `NextAuth.js` to a project create a file called `[...].ts` in `server/api/auth`. This contains the dynamic route handler for NextAuth.js which will also contain all of your global NextAuth.js configurations.
|
||||
Go to the API handler file (`server/api/auth/[...].ts`) and setup your providers. This file contains the dynamic route handler for Auth.js which will also contain all of your global Auth.js configurations.
|
||||
|
||||
Here's an example of what it looks like:
|
||||
|
||||
```ts
|
||||
// ~/server/api/auth/[...].ts
|
||||
import { NextAuthNuxtHandler } from 'next-auth-nuxt/handler'
|
||||
import GithubProvider from 'next-auth/providers/github'
|
||||
// server/api/auth/[...].ts
|
||||
|
||||
import { NuxtAuthHandler } from '@/lib/auth/server'
|
||||
import GithubProvider from '@auth/core/providers/github'
|
||||
import type { AuthOptions } from '@auth/core'
|
||||
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
|
||||
export const authOptions = {
|
||||
export const authOptions: AuthOptions = {
|
||||
secret: runtimeConfig.secret,
|
||||
providers: [
|
||||
GithubProvider({
|
||||
clientId: runtimeConfig.github.clientId,
|
||||
clientSecret: runtimeConfig.github.clientSecret
|
||||
}),
|
||||
],
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
export default NextAuthNuxtHandler(authOptions)
|
||||
export default NuxtAuthHandler(authOptions)
|
||||
```
|
||||
|
||||
All requests to `/api/auth/*` (`signIn`, `callback`, `signOut`, etc.) will automatically be handled by NextAuth.js.
|
||||
|
||||
### Frontend - Add Vue Composable
|
||||
|
||||
The `useSession()` Vue Composable is the easiest way to check if someone is signed in.
|
||||
|
||||
```html
|
||||
<script setup lang="ts">
|
||||
const { data: session } = useSession()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="session">
|
||||
Signed in as {{ session.user.email }} <br />
|
||||
<button @click="signOut">Sign out</button>
|
||||
</div>
|
||||
<div v-else>
|
||||
Not signed in <br />
|
||||
<button @click="signIn">Sign in</button>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Backend - API Route
|
||||
|
||||
To protect an API Route, you can use the `getServerSession()` method.
|
||||
|
||||
```ts
|
||||
import { getServerSession } from 'next-auth-nuxt/handler'
|
||||
import { authOptions } from '~/server/api/auth/[...]'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const session = await getServerSession(event, authOptions)
|
||||
|
||||
if (session) {
|
||||
return {
|
||||
content: 'This is protected content. You can access this content because you are signed in.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
error: 'You must be signed in to view the protected content on this page.'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
- Run `pnpm dev:generate` to generate type stubs.
|
||||
- Use `pnpm dev` to start `playground` in development mode.
|
||||
All requests to `/api/auth/*` (`signIn`, `callback`, `signOut`, etc.) will automatically be handled by Auth.js.
|
||||
|
||||
30
apps/playground-nuxt/app.vue
Normal file
30
apps/playground-nuxt/app.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div>
|
||||
<Header />
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
body {
|
||||
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';
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
li,
|
||||
p {
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
</style>
|
||||
1
apps/playground-nuxt/client.d.ts
vendored
1
apps/playground-nuxt/client.d.ts
vendored
@@ -1 +0,0 @@
|
||||
export * from './dist/runtime/client'
|
||||
139
apps/playground-nuxt/components/Header.vue
Normal file
139
apps/playground-nuxt/components/Header.vue
Normal file
@@ -0,0 +1,139 @@
|
||||
<script setup lang="ts">
|
||||
import { signIn, signOut } from '@/lib/auth/client'
|
||||
|
||||
const session = useSession()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header>
|
||||
<div class="signedInStatus">
|
||||
<p :class="['nojs-show', 'loaded']">
|
||||
<template v-if="session">
|
||||
<span v-if="session.user?.image" :style="{ backgroundImage: `url(${session.user.image})` }" class="avatar" />
|
||||
<span class="signedInText">
|
||||
<small>Signed in as</small><br>
|
||||
<strong>{{ session.user?.email || session.user?.name }}</strong>
|
||||
</span>
|
||||
<a href="/api/auth/signout" class="button" @click.prevent="signOut">Sign out</a>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="notSignedInText">You are not signed in</span>
|
||||
<a href="/api/auth/signin" class="buttonPrimary" @click.prevent="signIn">Sign in</a>
|
||||
</template>
|
||||
</p>
|
||||
</div>
|
||||
<nav>
|
||||
<ul class="navItems">
|
||||
<li class="navItem">
|
||||
<NuxtLink to="/">
|
||||
Home
|
||||
</NuxtLink>
|
||||
</li>
|
||||
<li class="navItem">
|
||||
<NuxtLink to="/protected">
|
||||
Protected
|
||||
</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.nojs-show {
|
||||
opacity: 1;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.signedInStatus {
|
||||
display: block;
|
||||
min-height: 4rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.loaded {
|
||||
position: relative;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 .6rem .6rem;
|
||||
padding: .6rem 1rem;
|
||||
margin: 0;
|
||||
background-color: rgba(0,0,0,.05);
|
||||
transition: all 0.2s ease-in;
|
||||
}
|
||||
|
||||
.loading {
|
||||
top: -2rem;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.signedInText,
|
||||
.notSignedInText {
|
||||
position: absolute;
|
||||
padding-top: .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: -.4rem;
|
||||
font-weight: 500;
|
||||
border-radius: .3rem;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
line-height: 1.4rem;
|
||||
padding: .7rem .8rem;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background-color: transparent;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.buttonPrimary {
|
||||
background-color: #346df1;
|
||||
border-color: #346df1;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: .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;
|
||||
}
|
||||
</style>
|
||||
5
apps/playground-nuxt/composables/useSession.ts
Normal file
5
apps/playground-nuxt/composables/useSession.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Session } from '@auth/core'
|
||||
|
||||
export default function useSession() {
|
||||
return useState<Session | null>('session', () => null)
|
||||
}
|
||||
1
apps/playground-nuxt/handler.d.ts
vendored
1
apps/playground-nuxt/handler.d.ts
vendored
@@ -1 +0,0 @@
|
||||
export * from './dist/runtime/server/handler'
|
||||
107
apps/playground-nuxt/lib/auth/client.ts
Normal file
107
apps/playground-nuxt/lib/auth/client.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import type {
|
||||
LiteralUnion,
|
||||
SignInOptions,
|
||||
SignInAuthorizationParams,
|
||||
SignOutParams,
|
||||
} from './types'
|
||||
import type {
|
||||
BuiltInProviderType,
|
||||
RedirectableProviderType,
|
||||
} from '@auth/core/providers'
|
||||
|
||||
/**
|
||||
* Client-side method to initiate a signin flow
|
||||
* or send the user to the signin page listing all possible providers.
|
||||
* Automatically adds the CSRF token to the request.
|
||||
*
|
||||
* [Documentation](https://next-auth.js.org/getting-started/client#signin)
|
||||
*/
|
||||
export async function signIn<
|
||||
P extends RedirectableProviderType | undefined = undefined
|
||||
>(
|
||||
providerId?: LiteralUnion<
|
||||
P extends RedirectableProviderType
|
||||
? P | BuiltInProviderType
|
||||
: BuiltInProviderType
|
||||
>,
|
||||
options?: SignInOptions,
|
||||
authorizationParams?: SignInAuthorizationParams
|
||||
) {
|
||||
const { callbackUrl = window.location.href, redirect = true } = options ?? {}
|
||||
|
||||
// TODO: Support custom providers
|
||||
const isCredentials = providerId === "credentials"
|
||||
const isEmail = providerId === "email"
|
||||
const isSupportingReturn = isCredentials || isEmail
|
||||
|
||||
// TODO: Handle custom base path
|
||||
const signInUrl = `/api/auth/${
|
||||
isCredentials ? "callback" : "signin"
|
||||
}/${providerId}`
|
||||
|
||||
const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}`
|
||||
|
||||
// TODO: Handle custom base path
|
||||
// TODO: Remove this since Sveltekit offers the CSRF protection via origin check
|
||||
const { csrfToken } = await $fetch("/api/auth/csrf")
|
||||
|
||||
console.log(_signInUrl)
|
||||
|
||||
const res = await fetch(_signInUrl, {
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"X-Auth-Return-Redirect": "1",
|
||||
},
|
||||
// @ts-expect-error -- ignore
|
||||
body: new URLSearchParams({
|
||||
...options,
|
||||
csrfToken,
|
||||
callbackUrl,
|
||||
}),
|
||||
})
|
||||
|
||||
const data = await res.clone().json()
|
||||
const error = new URL(data.url).searchParams.get("error")
|
||||
|
||||
if (redirect || !isSupportingReturn || !error) {
|
||||
// TODO: Do not redirect for Credentials and Email providers by default in next major
|
||||
window.location.href = data.url ?? callbackUrl
|
||||
// If url contains a hash, the browser does not reload the page. We reload manually
|
||||
if (data.url.includes("#")) window.location.reload()
|
||||
return
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs the user out, by removing the session cookie.
|
||||
* Automatically adds the CSRF token to the request.
|
||||
*
|
||||
* [Documentation](https://next-auth.js.org/getting-started/client#signout)
|
||||
*/
|
||||
export async function signOut(options?: SignOutParams) {
|
||||
const { callbackUrl = window.location.href } = options ?? {}
|
||||
// TODO: Custom base path
|
||||
// TODO: Remove this since Sveltekit offers the CSRF protection via origin check
|
||||
const csrfTokenResponse = await fetch("/api/auth/csrf")
|
||||
const { csrfToken } = await csrfTokenResponse.json()
|
||||
const res = await fetch(`/api/auth/signout`, {
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"X-Auth-Return-Redirect": "1",
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
csrfToken,
|
||||
callbackUrl,
|
||||
}),
|
||||
})
|
||||
const data = await res.json()
|
||||
|
||||
const url = data.url ?? callbackUrl
|
||||
window.location.href = url
|
||||
// If url contains a hash, the browser does not reload the page. We reload manually
|
||||
if (url.includes("#")) window.location.reload()
|
||||
}
|
||||
45
apps/playground-nuxt/lib/auth/server.ts
Normal file
45
apps/playground-nuxt/lib/auth/server.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { AuthHandler, AuthOptions, Session } from '@auth/core'
|
||||
import { fromNodeMiddleware, H3Event } from 'h3'
|
||||
import getURL from 'requrl'
|
||||
import { createMiddleware } from "@hattip/adapter-node";
|
||||
|
||||
export function NuxtAuthHandler (options: AuthOptions) {
|
||||
async function handler(ctx: { request: Request }) {
|
||||
options.trustHost ??= true
|
||||
|
||||
return AuthHandler(ctx.request, options)
|
||||
}
|
||||
|
||||
const middleware = createMiddleware(handler)
|
||||
|
||||
return fromNodeMiddleware(middleware)
|
||||
}
|
||||
|
||||
export async function getSession(
|
||||
event: H3Event,
|
||||
options: AuthOptions
|
||||
): Promise<Session | null> {
|
||||
options.trustHost ??= true
|
||||
|
||||
const headers = getRequestHeaders(event)
|
||||
const nodeHeaders = new Headers()
|
||||
|
||||
const url = new URL('/api/auth/session', getURL(event.node.req))
|
||||
|
||||
Object.keys(headers).forEach((key) => {
|
||||
nodeHeaders.append(key, headers[key] as any)
|
||||
})
|
||||
|
||||
const response = await AuthHandler(
|
||||
new Request(url, { headers: nodeHeaders }),
|
||||
options
|
||||
)
|
||||
|
||||
const { status = 200 } = response
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (!data || !Object.keys(data).length) return null
|
||||
if (status === 200) return data
|
||||
throw new Error(data.message)
|
||||
}
|
||||
42
apps/playground-nuxt/lib/auth/types.ts
Normal file
42
apps/playground-nuxt/lib/auth/types.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
// Taken from next-auth/react
|
||||
import type { BuiltInProviderType, ProviderType } from '@auth/core/providers'
|
||||
/**
|
||||
* Util type that matches some strings literally, but allows any other string as well.
|
||||
* @source https://github.com/microsoft/TypeScript/issues/29729#issuecomment-832522611
|
||||
*/
|
||||
export declare type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>);
|
||||
export interface ClientSafeProvider {
|
||||
id: LiteralUnion<BuiltInProviderType>;
|
||||
name: string;
|
||||
type: ProviderType;
|
||||
signinUrl: string;
|
||||
callbackUrl: string;
|
||||
}
|
||||
export interface SignInOptions extends Record<string, unknown> {
|
||||
/**
|
||||
* Specify to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from.
|
||||
*
|
||||
* [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl)
|
||||
*/
|
||||
callbackUrl?: string;
|
||||
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option) */
|
||||
redirect?: boolean;
|
||||
}
|
||||
export interface SignInResponse {
|
||||
error: string | undefined;
|
||||
status: number;
|
||||
ok: boolean;
|
||||
url: string | null;
|
||||
}
|
||||
/** Match `inputType` of `new URLSearchParams(inputType)` */
|
||||
export declare type SignInAuthorizationParams = string | string[][] | Record<string, string> | URLSearchParams;
|
||||
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1) */
|
||||
export interface SignOutResponse {
|
||||
url: string;
|
||||
}
|
||||
export interface SignOutParams<R extends boolean = true> {
|
||||
/** [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl-1) */
|
||||
callbackUrl?: string;
|
||||
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */
|
||||
redirect?: R;
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
import MyModule from '../src/module'
|
||||
|
||||
export default defineNuxtConfig({
|
||||
modules: [
|
||||
MyModule
|
||||
],
|
||||
// https://v3.nuxtjs.org/migration/runtime-config#runtime-config
|
||||
runtimeConfig: {
|
||||
secret: process.env.NEXTAUTH_SECRET,
|
||||
@@ -12,9 +7,11 @@ export default defineNuxtConfig({
|
||||
clientSecret: process.env.GITHUB_CLIENT_SECRET
|
||||
}
|
||||
},
|
||||
// https://v3.nuxtjs.org/guide/concepts/esm#aliasing-libraries
|
||||
// Fix for GithubProvider is not a function error in Vite
|
||||
alias: {
|
||||
'next-auth/providers/github': 'node_modules/next-auth/providers/github.js'
|
||||
vite: {
|
||||
define: {
|
||||
'process.env.NEXTAUTH_URL': JSON.stringify(process.env.NEXTAUTH_URL),
|
||||
'process.env.AUTH_TRUST_HOST': JSON.stringify(process.env.AUTH_TRUST_HOST),
|
||||
'process.env.VERCEL_URL': JSON.stringify(process.env.VERCEL_URL),
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,49 +1,22 @@
|
||||
{
|
||||
"name": "next-auth-nuxt",
|
||||
"type": "module",
|
||||
"version": "0.0.0",
|
||||
"packageManager": "pnpm@7.1.1",
|
||||
"license": "MIT",
|
||||
"main": "./dist/module.cjs",
|
||||
"types": "./dist/types.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/module.mjs",
|
||||
"require": "./dist/module.cjs"
|
||||
},
|
||||
"./handler": {
|
||||
"import": "./dist/runtime/server/handler.mjs",
|
||||
"types": "./dist/runtime/server/handler.d.ts"
|
||||
},
|
||||
"./client": {
|
||||
"import": "./dist/runtime/client/index.mjs",
|
||||
"types": "./dist/runtime/client/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"handler.d.ts",
|
||||
"client.d.ts"
|
||||
],
|
||||
"name": "playground-nuxt",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"prepack": "nuxt-module-build",
|
||||
"dev": "pnpm prepack && nuxi dev playground",
|
||||
"dev:build": "nuxi build playground",
|
||||
"dev:build:vercel": "NITRO_PRESET=vercel nuxi build playground",
|
||||
"dev:prepare": "nuxt-module-build --stub && nuxi prepare playground"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/kit": "^3.0.0-rc.13",
|
||||
"h3": "^0.8.6",
|
||||
"next-auth": "^4.16.2",
|
||||
"pathe": "^0.3.9"
|
||||
"build": "nuxt build",
|
||||
"dev": "export NODE_OPTIONS='--no-experimental-fetch' && nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/module-builder": "^0.2.0",
|
||||
"@nuxt/schema": "^3.0.0-rc.12",
|
||||
"@nuxtjs/eslint-config-typescript": "^11.0.0",
|
||||
"eslint": "^8.26.0",
|
||||
"nuxt": "^3.0.0-rc.13",
|
||||
"next-auth-nuxt": "workspace:*"
|
||||
"@nuxt/eslint-config": "^0.1.1",
|
||||
"eslint": "^8.29.0",
|
||||
"h3": "1.0.2",
|
||||
"nuxt": "3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/core": "workspace:*",
|
||||
"@hattip/adapter-node": "^0.0.22",
|
||||
"requrl": "^3.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
8
apps/playground-nuxt/pages/index.vue
Normal file
8
apps/playground-nuxt/pages/index.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Nuxt Auth Example</h1>
|
||||
<p>
|
||||
This is an example site to demonstrate how to use <a href="https://v3.nuxtjs.org/">Nuxt 3</a> with <a href="https://authjs.dev/">Auth.js</a> for authentication.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
18
apps/playground-nuxt/pages/protected.vue
Normal file
18
apps/playground-nuxt/pages/protected.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
const session = useSession()
|
||||
|
||||
definePageMeta({
|
||||
middleware: 'auth'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Protected Page</h1>
|
||||
<p>
|
||||
This is a protected content. You can access this content because you are
|
||||
signed in.
|
||||
</p>
|
||||
<p>Session expiry: {{ session?.expires }}</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,40 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<Header />
|
||||
<NuxtPage />
|
||||
<Footer />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
body {
|
||||
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';
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
li,
|
||||
p {
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
iframe {
|
||||
background: #ccc;
|
||||
border: 1px solid #ccc;
|
||||
height: 10rem;
|
||||
width: 100%;
|
||||
border-radius: .5rem;
|
||||
filter: invert(1);
|
||||
}
|
||||
</style>
|
||||
@@ -1,8 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Access Denied</h1>
|
||||
<p>
|
||||
<a href="/api/auth/signin">You must be signed in to view this page</a>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,30 +0,0 @@
|
||||
<template>
|
||||
<footer class="fotter">
|
||||
<hr>
|
||||
<ul class="navItems">
|
||||
<li class="navItem">
|
||||
<a href="https://github.com/nextauthjs/next-auth/tree/main/apps/playground-nuxt">Demo GitHub</a>
|
||||
</li>
|
||||
<li class="navItem">
|
||||
<a href="https://next-auth.js.org">Next.js Documentation</a>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.footer {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.navItems {
|
||||
margin-bottom: 1rem;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.navItem {
|
||||
display: inline-block;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -1,155 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useSession, signIn, signOut, computed } from '#imports'
|
||||
|
||||
const { data: session, status } = useSession()
|
||||
const loading = computed(() => status.value === 'loading')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header>
|
||||
<div class="signedInStatus">
|
||||
<p :class="['nojs-show', !session && loading ? 'loading' : 'loaded']">
|
||||
<template v-if="session">
|
||||
<span v-if="session.user?.image" :style="{ backgroundImage: `url(${session.user.image})` }" class="avatar" />
|
||||
<span class="signedInText">
|
||||
<small>Signed in as</small><br>
|
||||
<strong>{{ session.user?.email || session.user?.name }}</strong>
|
||||
</span>
|
||||
<a href="/api/auth/signout" class="button" @click.prevent="signOut">Sign out</a>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="notSignedInText">You are not signed in</span>
|
||||
<a href="/api/auth/signin" class="buttonPrimary" @click.prevent="signIn">Sign in</a>
|
||||
</template>
|
||||
</p>
|
||||
</div>
|
||||
<nav>
|
||||
<ul class="navItems">
|
||||
<li class="navItem">
|
||||
<NuxtLink to="/">
|
||||
Home
|
||||
</NuxtLink>
|
||||
</li>
|
||||
<li class="navItem">
|
||||
<NuxtLink to="/client">
|
||||
Client
|
||||
</NuxtLink>
|
||||
</li>
|
||||
<li class="navItem">
|
||||
<NuxtLink to="/server">
|
||||
Server
|
||||
</NuxtLink>
|
||||
</li>
|
||||
<li class="navItem">
|
||||
<NuxtLink to="/protected">
|
||||
Protected
|
||||
</NuxtLink>
|
||||
</li>
|
||||
<li class="navItem">
|
||||
<NuxtLink to="/api-example">
|
||||
API
|
||||
</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.nojs-show {
|
||||
opacity: 1;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.signedInStatus {
|
||||
display: block;
|
||||
min-height: 4rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.loaded {
|
||||
position: relative;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 .6rem .6rem;
|
||||
padding: .6rem 1rem;
|
||||
margin: 0;
|
||||
background-color: rgba(0,0,0,.05);
|
||||
transition: all 0.2s ease-in;
|
||||
}
|
||||
|
||||
.loading {
|
||||
top: -2rem;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.signedInText,
|
||||
.notSignedInText {
|
||||
position: absolute;
|
||||
padding-top: .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: -.4rem;
|
||||
font-weight: 500;
|
||||
border-radius: .3rem;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
line-height: 1.4rem;
|
||||
padding: .7rem .8rem;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background-color: transparent;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.buttonPrimary {
|
||||
background-color: #346df1;
|
||||
border-color: #346df1;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: .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;
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"name": "playground",
|
||||
"private": true
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>API Example</h1>
|
||||
<p>The examples below show responses from the example API endpoints.</p>
|
||||
<p>
|
||||
<em>You must be signed in to see responses.</em>
|
||||
</p>
|
||||
<h2>Session</h2>
|
||||
<p>/api/examples/session</p>
|
||||
<iframe src="/api/examples/session" />
|
||||
<h2>JSON Web Token</h2>
|
||||
<p>/api/examples/jwt</p>
|
||||
<iframe src="/api/examples/jwt" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Client Side Rendering</h1>
|
||||
<p>
|
||||
This page uses the <strong>useSession()</strong> Vue Composable in the <strong><Header/></strong> component.
|
||||
</p>
|
||||
<p>
|
||||
The <strong>useSession()</strong> Vue Composable is easy to use and allows pages to render very quickly.
|
||||
</p>
|
||||
<p>
|
||||
The advantage of this approach is that session state is shared between pages by using a provided session via <strong>Vue Plugin</strong> so
|
||||
that navigation between pages using <strong>useSession()</strong> is very fast.
|
||||
</p>
|
||||
<p>
|
||||
The disadvantage of <strong>useSession()</strong> is that it requires client side JavaScript.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,8 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Nuxt 3 + NextAuth.js Example</h1>
|
||||
<p>
|
||||
This is an example site to demonstrate how to use <a href="https://v3.nuxtjs.org/">Nuxt 3</a> with <a href="https://next-auth.js.org">NextAuth.js</a> for authentication.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,19 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useSession, useFetch, useLazyFetch } from '#imports'
|
||||
import AccessDenied from '~/components/AccessDenied.vue'
|
||||
|
||||
const { data: session } = useSession()
|
||||
const { data } = await useLazyFetch('/api/examples/protected', {
|
||||
server: false
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<AccessDenied v-if="!session" />
|
||||
<template v-else>
|
||||
<h1>Protected Page</h1>
|
||||
<p><strong>{{ data?.content || "\u00a0" }}</strong></p>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,24 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useFetch } from '#imports'
|
||||
|
||||
await useFetch('/api/examples/session')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Server Side Rendering</h1>
|
||||
<p>
|
||||
This page uses the <strong>getServerSession()</strong> method inside an api route and is fetched using the <strong>useFetch()</strong> composable.
|
||||
</p>
|
||||
<p>
|
||||
Using <strong>getServerSession()</strong> is the recommended approach if you need to
|
||||
support Server Side Rendering with authentication.
|
||||
</p>
|
||||
<p>
|
||||
The advantage of Server Side Rendering is this page does not require client side JavaScript.
|
||||
</p>
|
||||
<p>
|
||||
The disadvantage of Server Side Rendering is that this page is slower to render.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user