Compare commits

..

21 Commits

Author SHA1 Message Date
Balázs Orbán
b72eabb15d misc 2023-04-06 14:13:45 +02:00
Balázs Orbán
371f7bd4a1 fix logo link 2023-04-06 14:08:18 +02:00
Balázs Orbán
35f71bbcc8 fix readme 2023-04-06 14:07:11 +02:00
Balázs Orbán
97b1202ecb some fixes 2023-04-06 14:02:46 +02:00
Balázs Orbán
8423a05e95 feat(adapters): add Drizzle ORM adapter 2023-04-06 13:43:59 +02:00
Balázs Orbán
6c07331cc5 chore: upgrade turbo 2023-04-06 12:58:10 +02:00
Saurav Maheshkar
c8ef94b2be chore: move prettier and eslint configs under package.json (#7145) 2023-04-06 12:57:16 +02:00
jakzo
75a59fbd92 chore(docs): fix dynamodb typo (#7130)
fix: typo
2023-04-06 12:57:09 +02:00
Balázs Orbán
3dd47b0735 docs(example): remove unstable_ prefix 2023-03-31 05:01:58 +02:00
Balázs Orbán
4dc1d421f8 docs: mention client in OAuth config options
Related issue #7114
2023-03-30 18:34:30 +02:00
Balázs Orbán
99ca67f1cf docs: fix typo 2023-03-28 13:59:08 +02:00
Balázs Orbán
a087df8494 docs: fix some links 2023-03-28 13:47:53 +02:00
Sai Srikar Dumpeti
1aa4994de6 docs: respect color scheme (#7076) 2023-03-28 04:06:21 +02:00
Alan Hoskins
88023f69b9 fix(docs): remove extra install (#7081) 2023-03-27 15:47:32 +02:00
Alan Hoskins
b02057a72d fix(docs): fix broken links links (#7083)
Co-authored-by: Alan Hoskins <ahoskins@knowland.com>
2023-03-27 15:46:43 +02:00
Balázs Orbán
400da8c766 fix(providers): mention Email Address as required for Azure B2C
closes #7071
2023-03-27 15:44:23 +02:00
Andres Rodriguez
b48104801b chore(provider): added svg for Reddit (#7050)
Added svg for Reddit

Co-authored-by: Nico Domino <yo@ndo.dev>
2023-03-27 09:36:47 +02:00
Balázs Orbán
ccbbc800d2 docs: rephrase buttons on landing page 2023-03-27 02:06:33 +02:00
Abdulaziz Askaraliev
d7888263ca fix(providers): update Yandex to TypeScript (#7054)
* fix(providers): yandex add typescript.

* fix(providers): yandex add avatar to scope

* fix(providers): Yandex - add types & avatar scope

* fix(providers): Yandex - permissions list

* Apply suggestions from code review

* Apply suggestions from code review

* docs(provider): added comments for

* revert yandex.ts from next-auth/providers/

* fix(providers): yandex fix typo

* revert

* Update [...nextauth].ts

* Update yandex.ts

* Update yandex.ts

* Update [...nextauth].ts

---------

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2023-03-27 00:38:06 +01:00
Balázs Orbán
47d3151410 Merge branch 'main' of github.com:nextauthjs/next-auth 2023-03-27 01:32:54 +02:00
Balázs Orbán
7d264860ab chore: package builds as docs#dev task dependencies 2023-03-27 01:32:50 +02:00
42 changed files with 1520 additions and 955 deletions

View File

@@ -1,70 +0,0 @@
.eslintrc.js
.cache-loader
.DS_Store
.pnpm-debug.log
.turbo
.vscode/generated*
/_work
/actions-runner
node_modules
patches
pnpm-lock.yaml
.github/actions/issue-validator/index.mjs
*.cjs
*.js
*.d.ts
*.d.ts.map
.svelte-kit
.next
.nuxt
# --------------- Docs ---------------
.docusaurus
build
docs/docs/reference/core
docs/docs/reference/sveltekit
static
# --------------- Packages ---------------
coverage
dist
# @auth/core
packages/core/src/providers/oauth-types.ts
packages/core/src/lib/pages/styles.ts
# @auth/sveltekit
packages/frameworks-sveltekit/package
packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*
# next-auth
packages/next-auth/src/providers/oauth-types.ts
packages/next-auth/css/index.css
# Adapters
.branches
db.sqlite
dev.db
dynamodblocal-bin
firebase-debug.log
firestore-debug.log
migrations
test.schema.gql
# --------------- Apps ---------------
# Examples should have their own Prettier config since they are templates too
apps/example-sveltekit
# Development app
apps
# --------------- Tests ---------------
# TODO: these should be linted
packages/**/*test*

View File

@@ -1,75 +0,0 @@
// @ts-check
/** @type {import("eslint").ESLint.ConfigData} */
module.exports = {
env: { browser: true, es2022: true, node: true },
extends: ["eslint:recommended", "prettier"],
overrides: [
{
files: ["*.ts", "*.tsx"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: ["./packages/**/tsconfig.json", "./apps/**/tsconfig.json"],
},
settings: { react: { version: "18" } },
extends: [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"standard-with-typescript",
"prettier",
],
rules: {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/method-signature-style": "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"react/prop-types": "off",
"react/no-unescaped-entities": "off",
},
},
{
files: ["*.test.ts", "*.test.js"],
extends: ["plugin:jest/recommended"],
env: { jest: true },
},
{
files: ["docs/**"],
plugins: ["@docusaurus"],
extends: ["plugin:@docusaurus/recommended"],
},
{
// TODO: Expand to all packages
files: ["packages/{core,sveltekit}/*.ts"],
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/frameworks-sveltekit"],
plugins: ["svelte3"],
overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }],
settings: {
"svelte3/typescript": () => require("typescript"),
},
parserOptions: { sourceType: "module", ecmaVersion: 2020 },
env: { browser: true, es2017: true, node: true },
},
],
parserOptions: {
sourceType: "module",
ecmaVersion: "latest",
ecmaFeatures: { jsx: true },
},
root: true,
}

1
.gitignore vendored
View File

@@ -63,6 +63,7 @@ packages/adapter-prisma/prisma/dev.db
packages/adapter-prisma/prisma/migrations
db.sqlite
packages/adapter-supabase/supabase/.branches
packages/adapter-drizzle/drizzle
# Tests
coverage

View File

@@ -1,22 +0,0 @@
// @ts-check
/** @type {import("prettier").Config} */
module.exports = {
semi: false,
singleQuote: false,
overrides: [
{
files: [
"apps/dev/nextjs/pages/api/auth/[...nextauth].ts",
"docs/{sidebars,docusaurus.config}.js",
],
options: { printWidth: 150 },
},
{
files: ["**/*package.json"],
options: {
trailingComma: "none",
},
},
],
}

View File

@@ -52,6 +52,10 @@ TWITTER_SECRET=
WIKIMEDIA_ID=
WIKIMEDIA_SECRET=
# Yandex OAuth. new app -> https://oauth.yandex.com/client/new/id
YANDEX_ID=
YANDEX_SECRET=
# Example configuration for a Gmail account (will need SMTP enabled)
EMAIL_SERVER=smtps://user@gmail.com:password@smtp.gmail.com:465
EMAIL_FROM=user@gmail.com

View File

@@ -34,6 +34,7 @@ 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 Yandex from "@auth/core/providers/yandex"
import Vk from "@auth/core/providers/vk"
import Wikimedia from "@auth/core/providers/wikimedia"
import WorkOS from "@auth/core/providers/workos"
@@ -120,6 +121,7 @@ export const authConfig: AuthConfig = {
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 }),
Yandex({ clientId: process.env.YANDEX_ID, clientSecret: process.env.YANDEX_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 }),

View File

@@ -1,4 +1,4 @@
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "./api/auth/[...nextauth]"
import Layout from "../components/layout"
@@ -38,7 +38,7 @@ export default function ServerSidePage() {
export async function getServerSideProps(context: GetServerSidePropsContext) {
return {
props: {
session: await unstable_getServerSession(
session: await getServerSession(
context.req,
context.res,
authOptions

View File

@@ -46,7 +46,7 @@ export default NextAuth({
```
:::note
Check the [Credentials Provider options](/reference/providers/credentials) for further customization
Check the [Credentials Provider options](/reference/core/providers_credentials) for further customization
:::
Note that we only need to define an `authorize` method that is in charge of receiving the credentials inserted by the user and call the authorization service.

View File

@@ -66,7 +66,7 @@ Nice! We're getting there. Now we need to read supply this values as the configu
```ts title="pages/api/auth/[...nextauth].ts"
import NextAuth from "next-auth"
import EmailProvider from "next-auth/providers/email"
import Email from "next-auth/providers/email"
export default NextAuth({
providers: [

View File

@@ -239,7 +239,7 @@ Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.1
## `nodemailer`
Like `typeorm` and `prisma`, [`nodemailer`](https://npmjs.com/package/nodemailer) is no longer included as a dependency by default. If you are using the Email provider you must install it in your project manually, or use any other Email library in the [`sendVerificationRequest`](/reference/providers/email) callback. This reduces bundle size for those not actually using the Email provider. Remember, when using the Email provider, it is mandatory to also use a database adapter due to the fact that verification tokens need to be persisted longer term for the magic link functionality to work.
Like `typeorm` and `prisma`, [`nodemailer`](https://npmjs.com/package/nodemailer) is no longer included as a dependency by default. If you are using the Email provider you must install it in your project manually, or use any other Email library in the [`sendVerificationRequest`](/guides/providers/email) callback. This reduces bundle size for those not actually using the Email provider. Remember, when using the Email provider, it is mandatory to also use a database adapter due to the fact that verification tokens need to be persisted longer term for the magic link functionality to work.
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.2

View File

@@ -17,7 +17,7 @@ The functionality provided for credentials-based authentication is intentionally
The **Credentials Provider** comes with a set of default options:
- [Credentials Provider options](/reference/providers/credentials)
- [Credentials Provider options](/reference/core/providers_credentials)
You can override any of the options to suit your own use case.

View File

@@ -23,7 +23,7 @@ The Email Provider can be used with both JSON Web Tokens and database sessions,
The **Email Provider** comes with a set of default options:
- [Email Provider options](/reference/providers/email)
- [Email Provider options](/guides/providers/email)
You can override any of the options to suit your own use case.

View File

@@ -9,6 +9,10 @@ Using a Auth.js / NextAuth.js adapter you can connect to any database service or
<img src="/img/adapters/dgraph.png" width="30" />
<h4 class="adapter-card__title">Dgraph Adapter</h4>
</a>
<a href="/reference/adapter/drizzle" class="adapter-card">
<img src="/img/adapters/drizzle-orm.png" width="30" />
<h4 class="adapter-card__title">Drizzle ORM Adapter</h4>
</a>
<a href="/reference/adapter/dynamodb" class="adapter-card">
<img src="/img/adapters/dynamodb.png" width="30" />
<h4 class="adapter-card__title">DynamoDB Adapter</h4>
@@ -52,7 +56,7 @@ Using a Auth.js / NextAuth.js adapter you can connect to any database service or
<a href="/reference/adapter/typeorm" class="adapter-card">
<img src="/img/adapters/typeorm.png" width="30" />
<h4 class="adapter-card__title">TypeORM Adapter</h4>
</a>
</a>
<a href="/reference/adapter/upstash-redis" class="adapter-card">
<img src="/img/adapters/upstash-redis.svg" width="30" />
<h4 class="adapter-card__title">Upstash Adapter</h4>
@@ -133,7 +137,7 @@ If a user first signs in with OAuth then their email address is automatically po
This provides a way to contact users and for users to maintain access to their account and sign in using email in the event they are unable to sign in with the OAuth provider in future (if the [Email Provider](/getting-started/email-tutorial) is configured).
:::
User creation in the database is automatic, and happens when the user is logging in for the first time with a provider. The default data saved is `id`, `name`, `email` and `image`. You can add more profile data by returning extra fields in your [OAuth provider's `profile()`](/reference/providers/oauth) callback.
User creation in the database is automatic, and happens when the user is logging in for the first time with a provider. The default data saved is `id`, `name`, `email` and `image`. You can add more profile data by returning extra fields in your [OAuth provider](/guides/providers/custom-provider)'s [`profile()`](/reference/core/providers#profile) callback.
### Account
@@ -174,7 +178,7 @@ A single User can have multiple open Verification Tokens (e.g. to sign in to dif
It has been designed to be extendable for other verification purposes in the future (e.g. 2FA / short codes).
:::note
Auth.js makes sure that every token is usable only once, and by default has a short (1 day, can be configured by [`maxAge`](/reference/providers/email)) lifetime. If your user did not manage to finish the sign-in flow in time, they will have to start the sign-in process again.
Auth.js makes sure that every token is usable only once, and by default has a short (1 day, can be configured by [`maxAge`](/guides/providers/email)) lifetime. If your user did not manage to finish the sign-in flow in time, they will have to start the sign-in process again.
:::
:::tip
@@ -188,4 +192,4 @@ Auth.js / NextAuth.js uses `camelCase` for its own database rows, while respecti
## TypeScript
Check out the [`@auth/core/adapters` API Reference](/reference/core/adapters) documentation.
Check out the [`@auth/core/adapters` API Reference](/reference/core/adapters) documentation.

View File

@@ -262,6 +262,7 @@ const docusaurusConfig = {
},
],
typedocAdapter("Dgraph"),
typedocAdapter("Drizzle ORM"),
typedocAdapter("DynamoDB"),
typedocAdapter("Fauna"),
typedocAdapter("Firebase"),

View File

@@ -53,6 +53,7 @@ module.exports = {
items: [
{ type: "doc", id: "reference/adapter/dgraph/index" },
{ type: "doc", id: "reference/adapter/dynamodb/index" },
{ type: "doc", id: "reference/adapter/drizzle/index" },
{ type: "doc", id: "reference/adapter/fauna/index" },
{ type: "doc", id: "reference/adapter/firebase/index" },
{ type: "doc", id: "reference/adapter/mikro-orm/index" },

View File

@@ -25,6 +25,10 @@
transition: 0.2s background-color ease-in-out;
}
html[data-theme="dark"] .adapter-card {
color: #f5f5f5;
}
.adapter-card:hover {
text-decoration: none;
color: black;

View File

@@ -128,16 +128,6 @@ export default function Home() {
<p className="hero__subtitle">{siteConfig.tagline}</p>
</div>
<div className={styles.buttons}>
<Link
className={classnames(
"button button--primary button--lg rounded-pill button-start",
styles.button,
styles.buttonStart
)}
to={useBaseUrl("/getting-started/introduction")}
>
Get Started
</Link>
<a
className={classnames(
"button button--outline button--secondary button--lg rounded-pill",
@@ -145,7 +135,7 @@ export default function Home() {
)}
href="https://next-auth-example.vercel.app"
>
<img src="/img/framework-nextjs-white.svg" height="48" width="48" />
Next.js Demo
</a>
<a
className={classnames(
@@ -154,7 +144,7 @@ export default function Home() {
)}
href="https://sveltekit-auth-example.vercel.app"
>
<img src="/img/framework-sveltekit.svg" height="48" width="48" />
SvelteKit Demo
</a>
<a
className={classnames(
@@ -163,8 +153,17 @@ export default function Home() {
)}
href="https://auth-solid.vercel.app"
>
<img src="/img/framework-solidstart.svg" height="48" width="48" />
SolidStart Demo
</a>
<Link
className={classnames(
"button button--primary button--lg rounded-pill",
styles.button
)}
to={useBaseUrl("/getting-started/introduction")}
>
Get Started
</Link>
</div>
</div>
<div className="hero-marquee">

View File

@@ -34,31 +34,17 @@
}
}
.frameworkWrapper {
display: flex;
flex-direction: column;
justify-content: center;
padding: 4rem 1rem 2rem 1rem;
align-items: center;
}
.buttons {
display: flex;
align-items: center;
justify-content: center;
padding: 4rem 1rem 0 1rem;
flex-wrap: wrap;
padding: 2rem 0;
gap: 1rem;
color: #fff;
}
.button {
margin: 0 1rem;
}
.buttonStart {
margin: 0 2rem;
color: red;
margin: 0 0.5rem;
}
.features {

BIN
docs/static/img/adapters/drizzle-orm.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" aria-label="Next.js logomark" class="next-mark_root__wLeec" data-theme="dark" height="80" role="img" viewBox="0 0 180 180" width="80"><mask height="180" id="mask0_408_134" maskUnits="userSpaceOnUse" style="mask-type:alpha" width="180" x="0" y="0"><circle cx="90" cy="90" fill="black" r="90"></circle></mask><g mask="url(#mask0_408_134)"><circle cx="90" cy="90" data-circle="true" fill="black" r="90" stroke="white" stroke-width="6px"></circle><path d="M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z" fill="url(#paint0_linear_408_134)"></path><rect fill="url(#paint1_linear_408_134)" height="72" width="12" x="115" y="54"></rect></g><defs><linearGradient gradientUnits="userSpaceOnUse" id="paint0_linear_408_134" x1="109" x2="144.5" y1="116.5" y2="160.5"><stop stop-color="white"></stop><stop offset="1" stop-color="white" stop-opacity="0"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="paint1_linear_408_134" x1="121" x2="120.799" y1="54" y2="106.875"><stop stop-color="white"></stop><stop offset="1" stop-color="white" stop-opacity="0"></stop></linearGradient></defs></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 166 155.3"><defs><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="27.5" y1="3" x2="152" y2="63.5"><stop offset=".1" stop-color="#76b3e1"/><stop offset=".3" stop-color="#dcf2fd"/><stop offset="1" stop-color="#76b3e1"/></linearGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="95.8" y1="32.6" x2="74" y2="105.2"><stop offset="0" stop-color="#76b3e1"/><stop offset=".5" stop-color="#4377bb"/><stop offset="1" stop-color="#1f3b77"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="18.4" y1="64.2" x2="144.3" y2="149.8"><stop offset="0" stop-color="#315aa9"/><stop offset=".5" stop-color="#518ac8"/><stop offset="1" stop-color="#315aa9"/></linearGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="75.2" y1="74.5" x2="24.4" y2="260.8"><stop offset="0" stop-color="#4377bb"/><stop offset=".5" stop-color="#1a336b"/><stop offset="1" stop-color="#1a336b"/></linearGradient></defs><path d="M163 35S110-4 69 5l-3 1c-6 2-11 5-14 9l-2 3-15 26 26 5c11 7 25 10 38 7l46 9 18-30z" fill="#76b3e1"/><path d="M163 35S110-4 69 5l-3 1c-6 2-11 5-14 9l-2 3-15 26 26 5c11 7 25 10 38 7l46 9 18-30z" opacity=".3" fill="url(#a)"/><path d="M52 35l-4 1c-17 5-22 21-13 35 10 13 31 20 48 15l62-21S92 26 52 35z" fill="#518ac8"/><path d="M52 35l-4 1c-17 5-22 21-13 35 10 13 31 20 48 15l62-21S92 26 52 35z" opacity=".3" fill="url(#b)"/><path d="M134 80a45 45 0 00-48-15L24 85 4 120l112 19 20-36c4-7 3-15-2-23z" fill="url(#c)"/><path d="M114 115a45 45 0 00-48-15L4 120s53 40 94 30l3-1c17-5 23-21 13-34z" fill="url(#d)"/></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.1566,22.8189c-10.4-14.8851-30.94-19.2971-45.7914-9.8348L22.2825,29.6078A29.9234,29.9234,0,0,0,8.7639,49.6506a31.5136,31.5136,0,0,0,3.1076,20.2318A30.0061,30.0061,0,0,0,7.3953,81.0653a31.8886,31.8886,0,0,0,5.4473,24.1157c10.4022,14.8865,30.9423,19.2966,45.7914,9.8348L84.7167,98.3921A29.9177,29.9177,0,0,0,98.2353,78.3493,31.5263,31.5263,0,0,0,95.13,58.117a30,30,0,0,0,4.4743-11.1824,31.88,31.88,0,0,0-5.4473-24.1157" style="fill:#ff3e00"/><path d="M45.8171,106.5815A20.7182,20.7182,0,0,1,23.58,98.3389a19.1739,19.1739,0,0,1-3.2766-14.5025,18.1886,18.1886,0,0,1,.6233-2.4357l.4912-1.4978,1.3363.9815a33.6443,33.6443,0,0,0,10.203,5.0978l.9694.2941-.0893.9675a5.8474,5.8474,0,0,0,1.052,3.8781,6.2389,6.2389,0,0,0,6.6952,2.485,5.7449,5.7449,0,0,0,1.6021-.7041L69.27,76.281a5.4306,5.4306,0,0,0,2.4506-3.631,5.7948,5.7948,0,0,0-.9875-4.3712,6.2436,6.2436,0,0,0-6.6978-2.4864,5.7427,5.7427,0,0,0-1.6.7036l-9.9532,6.3449a19.0329,19.0329,0,0,1-5.2965,2.3259,20.7181,20.7181,0,0,1-22.2368-8.2427,19.1725,19.1725,0,0,1-3.2766-14.5024,17.9885,17.9885,0,0,1,8.13-12.0513L55.8833,23.7472a19.0038,19.0038,0,0,1,5.3-2.3287A20.7182,20.7182,0,0,1,83.42,29.6611a19.1739,19.1739,0,0,1,3.2766,14.5025,18.4,18.4,0,0,1-.6233,2.4357l-.4912,1.4978-1.3356-.98a33.6175,33.6175,0,0,0-10.2037-5.1l-.9694-.2942.0893-.9675a5.8588,5.8588,0,0,0-1.052-3.878,6.2389,6.2389,0,0,0-6.6952-2.485,5.7449,5.7449,0,0,0-1.6021.7041L37.73,51.719a5.4218,5.4218,0,0,0-2.4487,3.63,5.7862,5.7862,0,0,0,.9856,4.3717,6.2437,6.2437,0,0,0,6.6978,2.4864,5.7652,5.7652,0,0,0,1.602-.7041l9.9519-6.3425a18.978,18.978,0,0,1,5.2959-2.3278,20.7181,20.7181,0,0,1,22.2368,8.2427,19.1725,19.1725,0,0,1,3.2766,14.5024,17.9977,17.9977,0,0,1-8.13,12.0532L51.1167,104.2528a19.0038,19.0038,0,0,1-5.3,2.3287" style="fill:#fff"/></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

6
docs/static/img/providers/reddit.svg vendored Normal file
View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" height="32" width="32">
<g>
<circle fill="#FF4500" cx="10" cy="10" r="10"/>
<path fill="#FFF" d="M16.67,10A1.46,1.46,0,0,0,14.2,9a7.12,7.12,0,0,0-3.85-1.23L11,4.65,13.14,5.1a1,1,0,1,0,.13-0.61L10.82,4a0.31,0.31,0,0,0-.37.24L9.71,7.71a7.14,7.14,0,0,0-3.9,1.23A1.46,1.46,0,1,0,4.2,11.33a2.87,2.87,0,0,0,0,.44c0,2.24,2.61,4.06,5.83,4.06s5.83-1.82,5.83-4.06a2.87,2.87,0,0,0,0-.44A1.46,1.46,0,0,0,16.67,10Zm-10,1a1,1,0,1,1,1,1A1,1,0,0,1,6.67,11Zm5.81,2.75a3.84,3.84,0,0,1-2.47.77,3.84,3.84,0,0,1-2.47-.77,0.27,0.27,0,0,1,.38-0.38A3.27,3.27,0,0,0,10,14a3.28,3.28,0,0,0,2.09-.61A0.27,0.27,0,1,1,12.48,13.79Zm-0.18-1.71a1,1,0,1,1,1-1A1,1,0,0,1,12.29,12.08Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 736 B

1
docs/static/img/providers/yandex.svg vendored Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,256,256" width="480px" height="480px" fill-rule="nonzero"><g transform="translate(32,32) scale(0.75,0.75)"><g fill-opacity="0" fill="#ff0000" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M-42.66667,298.66667v-341.33333h341.33333v341.33333z" id="bgRectangle"></path></g><g fill="#ff0000" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M128,292.57143c-90.89029,0 -164.57143,-73.68114 -164.57143,-164.57143v0c0,-90.89029 73.68114,-164.57143 164.57143,-164.57143v0c90.89029,0 164.57143,73.68114 164.57143,164.57143v0c0,90.89029 -73.68114,164.57143 -164.57143,164.57143z" id="shape"></path></g><g fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(5.33333,5.33333)"><path d="M21.413,47.315c1.685,0.076 3.206,-0.076 4.891,0c-0.383,-4.097 0.719,-8.451 0.297,-12.544c-0.118,-1.142 0.076,-2.779 0.171,-3.924c0.102,-1.229 1.069,-3.553 1.533,-4.696c3.541,-8.731 5.77,-15.742 8.924,-24.62c-1.548,-0.029 -3.702,0.029 -5.25,0c-2.934,7.419 -5.846,15.183 -8.022,22.859c-3.659,-6.121 -5.157,-12.182 -7.055,-18.386c-0.13,-0.424 -0.284,-0.885 -0.66,-1.12c-0.247,-0.154 -0.549,-0.183 -0.839,-0.205c-1.56,-0.118 -3.126,-0.149 -4.689,-0.09c3.636,7.742 6.793,16.44 9.267,24.628c0.411,1.36 0.806,2.729 1.013,4.134c0.218,1.48 0.447,2.718 0.453,4.213c0.009,2.887 -0.044,6.865 -0.034,9.751z"></path><path d="M37.228,1.033c-1.75,-0.028 -3.5,0.028 -5.25,0c-0.238,-0.004 -0.401,0.161 -0.482,0.367c-2.823,7.142 -5.525,14.344 -7.685,21.717c-2.11,-3.802 -3.592,-7.875 -4.862,-12.033c-0.335,-1.095 -0.659,-2.193 -0.986,-3.291c-0.27,-0.904 -0.439,-2.011 -0.95,-2.815c-0.522,-0.821 -1.483,-0.798 -2.35,-0.848c-1.315,-0.076 -2.633,-0.086 -3.95,-0.041c-0.401,0.014 -0.593,0.409 -0.432,0.752c2.538,5.416 4.725,10.992 6.675,16.645c1.884,5.463 3.992,11.069 3.99,16.917c0,2.97 -0.043,5.941 -0.034,8.911c0.001,0.199 0.102,0.33 0.234,0.406c0.072,0.051 0.156,0.09 0.266,0.094c1.631,0.063 3.261,-0.063 4.891,0c0.253,0.01 0.523,-0.238 0.5,-0.5c-0.29,-3.347 0.333,-6.672 0.39,-10.014c0.026,-1.503 -0.185,-2.988 -0.088,-4.49c0.082,-1.276 0.2,-2.483 0.603,-3.701c0.908,-2.743 2.12,-5.396 3.142,-8.098c1.122,-2.965 2.185,-5.951 3.229,-8.944c1.21,-3.467 2.4,-6.941 3.629,-10.402c0.114,-0.314 -0.175,-0.627 -0.48,-0.632zM30.286,19.685c-1.051,2.814 -2.242,5.576 -3.274,8.396c-0.426,1.163 -0.695,2.274 -0.806,3.505c-0.061,0.682 -0.122,1.366 -0.138,2.051c-0.018,0.764 0.083,1.516 0.114,2.278c0.148,3.64 -0.621,7.255 -0.403,10.893c-1.288,-0.021 -2.575,0.037 -3.862,0.015c0.012,-5.353 0.438,-10.808 -0.961,-16.031c-1.566,-5.848 -3.647,-11.615 -5.86,-17.245c-1.123,-2.857 -2.331,-5.681 -3.617,-8.468c0.98,-0.018 1.96,-0.013 2.939,0.038c0.445,0.023 1.19,-0.067 1.573,0.2c0.355,0.247 0.446,0.872 0.561,1.249c0.612,2.017 1.195,4.043 1.828,6.053c1.316,4.174 2.906,8.253 5.146,12.025c0.22,0.371 0.796,0.295 0.914,-0.119c2.174,-7.647 4.961,-15.101 7.878,-22.492c1.403,0.014 2.805,-0.007 4.208,0c-2.082,5.883 -4.056,11.805 -6.24,17.652z"></path></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -40,7 +40,7 @@
"eslint-plugin-svelte3": "^4.0.0",
"prettier": "2.8.1",
"prettier-plugin-svelte": "^2.8.1",
"turbo": "1.6.3",
"turbo": "1.8.8",
"typescript": "4.9.4"
},
"engines": {
@@ -61,5 +61,205 @@
"patchedDependencies": {
"@balazsorban/monorepo-release@0.1.8": "patches/@balazsorban__monorepo-release@0.1.8.patch"
}
},
"eslintIgnore": [
".eslintrc.js",
".cache-loader",
".DS_Store",
".pnpm-debug.log",
".turbo",
".vscode/generated*",
"/_work",
"/actions-runner",
"node_modules",
"patches",
"pnpm-lock.yaml",
".github/actions/issue-validator/index.mjs",
"*.cjs",
"*.js",
"*.d.ts",
"*.d.ts.map",
".svelte-kit",
".next",
".nuxt",
".docusaurus",
"build",
"docs/docs/reference/core",
"docs/docs/reference/sveltekit",
"static",
"coverage",
"dist",
"packages/core/src/providers/oauth-types.ts",
"packages/core/src/lib/pages/styles.ts",
"packages/frameworks-sveltekit/package",
"packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*",
"packages/next-auth/src/providers/oauth-types.ts",
"packages/next-auth/css/index.css",
".branches",
"db.sqlite",
"dev.db",
"dynamodblocal-bin",
"firebase-debug.log",
"firestore-debug.log",
"migrations",
"test.schema.gql",
"apps/example-sveltekit",
"apps",
"packages/**/*test*"
],
"eslintConfig": {
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"eslint:recommended",
"prettier"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": [
"./packages/**/tsconfig.json",
"./apps/**/tsconfig.json"
]
},
"settings": {
"react": {
"version": "18"
}
},
"extends": [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"standard-with-typescript",
"prettier"
],
"rules": {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/method-signature-style": "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"react/prop-types": "off",
"react/no-unescaped-entities": "off"
}
},
{
"files": [
"*.test.ts",
"*.test.js"
],
"extends": [
"plugin:jest/recommended"
],
"env": {
"jest": true
}
},
{
"files": [
"docs/**"
],
"plugins": [
"@docusaurus"
],
"extends": [
"plugin:@docusaurus/recommended"
]
},
{
"files": [
"packages/{core,sveltekit}/*.ts"
],
"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/frameworks-sveltekit"
],
"plugins": [
"svelte3"
],
"overrides": [
{
"files": [
"*.svelte"
],
"processor": "svelte3/svelte3"
}
],
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2020
},
"env": {
"browser": true,
"es2017": true,
"node": true
}
}
],
"parserOptions": {
"sourceType": "module",
"ecmaVersion": "latest",
"ecmaFeatures": {
"jsx": true
}
},
"root": true
},
"prettier": {
"semi": false,
"singleQuote": false,
"overrides": [
{
"files": [
"apps/dev/nextjs/pages/api/auth/[...nextauth].ts",
"docs/{sidebars,docusaurus.config}.js"
],
"options": {
"printWidth": 150
}
},
{
"files": [
"**/*package.json"
],
"options": {
"trailingComma": "none"
}
}
]
}
}

View File

@@ -0,0 +1,28 @@
<p align="center">
<br/>
<a href="https://authjs.dev" target="_blank">
<img height="64px" src="https://authjs.dev/img/logo/logo-sm.png" />
</a>
<a href="https://github.com/drizzle-team/drizzle-orm" target="_blank">
<img height="64px" src="https://authjs.dev/img/adapters/drizzle-orm.png"/>
</a>
<h3 align="center"><b>Drizzle ORM Adapter</b> - NextAuth.js / Auth.js</a></h3>
<p align="center" style="align: center;">
<a href="https://npm.im/@auth/drizzle-adapter">
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
</a>
<a href="https://npm.im/@auth/drizzle-adapter">
<img alt="npm" src="https://img.shields.io/npm/v/@auth/drizzle-adapter?color=green&label=@auth/drizzle-adapter&style=flat-square">
</a>
<a href="https://www.npmtrends.com/@auth/drizzle-adapter">
<img src="https://img.shields.io/npm/dm/@auth/drizzle-adapter?label=%20downloads&style=flat-square" alt="Downloads" />
</a>
<a href="https://github.com/nextauthjs/next-auth/stargazers">
<img src="https://img.shields.io/github/stars/nextauthjs/next-auth?style=flat-square" alt="Github Stars" />
</a>
</p>
</p>
---
Check out the documentation at [authjs.dev](https://authjs.dev/reference/adapter/drizzle).

View File

@@ -0,0 +1,57 @@
{
"name": "@auth/drizzle-adapter",
"version": "0.0.1",
"description": "Drizzle ORM adapter for Auth.js",
"homepage": "https://authjs.dev/reference/adapter/drizzle",
"repository": "https://github.com/nextauthjs/next-auth",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
},
"author": "Anthony Shew",
"license": "ISC",
"type": "module",
"exports": {
".": {
"types": "./index.d.ts",
"import": "./index.js"
}
},
"keywords": [
"auth.js",
"next-auth",
"next.js",
"oauth",
"drizzle"
],
"private": false,
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf *.js *.d.ts* ./drizzle db.sqlite",
"test:init": "pnpm clean && drizzle-kit generate:sqlite --schema=src/schema.ts --breakpoints",
"test": "pnpm test:init && jest",
"build": "pnpm clean && drizzle-kit generate:sqlite --schema=src/schema.ts && tsc",
"dev": "drizzle-kit generate:sqlite --schema=src/schema.ts && tsc -w"
},
"files": [
"src",
"*.js",
"*.d.ts*"
],
"peerDependencies": {
"drizzle-orm": "^0.23.5"
},
"devDependencies": {
"@next-auth/adapter-test": "workspace:*",
"@types/better-sqlite3": "^7.6.3",
"better-sqlite3": "^8.2.0",
"drizzle-kit": "^0.17.3",
"drizzle-orm": "^0.23.5",
"jest": "^27.4.3",
"next-auth": "workspace:*"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
}
}

View File

@@ -0,0 +1,248 @@
/**
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center", padding: 16}}>
* <p style={{fontWeight: "normal"}}>Official <a href="https://github.com/drizzle-team/drizzle-orm">Drizzle ORM</a> adapter for Auth.js / NextAuth.js.</p>
* <a href="https://github.com/drizzle-team/drizzle-orm">
* <img style={{display: "block"}} src="https://authjs.dev/img/adapters/drizzle-orm.png" width="38" />
* </a>
* </div>
*
* ## Installation
*
* ```bash npm2yarn2pnpm
* npm install next-auth drizzle-orm @auth/drizzle-adapter
* npm install drizzle-kit --save-dev
* ```
*
* @module @auth/drizzle-adapter
*/
import {
accounts,
users,
sessions,
verificationTokens,
type DrizzleClient,
} from "./schema"
import { and, eq } from "drizzle-orm/expressions"
import type { Adapter } from "next-auth/adapters"
/**
* ## Setup
*
* Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object:
*
* ```js title="pages/api/auth/[...nextauth].js"
* import NextAuth from "next-auth"
* import GoogleProvider from "next-auth/providers/google"
* import { DrizzleAdapter } from "@auth/drizzle-adapter"
* import { db } from "./db-schema"
*
* export default NextAuth({
* adapter: DrizzleAdapter(db),
* providers: [
* GoogleProvider({
* clientId: process.env.GOOGLE_CLIENT_ID,
* clientSecret: process.env.GOOGLE_CLIENT_SECRET,
* }),
* ],
* })
* ```
*
* ## Advanced usage
*
* ### Create the Drizzle schema from scratch
*
* You'll need to create a database schema that includes the minimal schema for a `next-auth` adapter.
* Be sure to use the Drizzle driver version that you're using for your project.
*
* > This schema is adapted for use in Drizzle and based upon our main [schema](https://authjs.dev/reference/adapters#models)
*
*
* ```json title="db-schema.ts"
*
* import { integer, pgTable, text, primaryKey } from 'drizzle-orm/pg-core';
* import { drizzle } from 'drizzle-orm/node-postgres';
* import { migrate } from 'drizzle-orm/node-postgres/migrator';
* import { Pool } from 'pg'
* import { ProviderType } from 'next-auth/providers';
*
* export const users = pgTable('users', {
* id: text('id').notNull().primaryKey(),
* name: text('name'),
* email: text("email").notNull(),
* emailVerified: integer("emailVerified"),
* image: text("image"),
* });
*
* export const accounts = pgTable("accounts", {
* userId: text("userId").notNull().references(() => users.id, { onDelete: "cascade" }),
* type: text("type").$type<ProviderType>().notNull(),
* provider: text("provider").notNull(),
* providerAccountId: text("providerAccountId").notNull(),
* refresh_token: text("refresh_token"),
* access_token: text("access_token"),
* expires_at: integer("expires_at"),
* token_type: text("token_type"),
* scope: text("scope"),
* id_token: text("id_token"),
* session_state: text("session_state"),
* }, (account) => ({
* _: primaryKey(account.provider, account.providerAccountId)
* }))
*
* export const sessions = pgTable("sessions", {
* userId: text("userId").notNull().references(() => users.id, { onDelete: "cascade" }),
* sessionToken: text("sessionToken").notNull().primaryKey(),
* expires: integer("expires").notNull(),
* })
*
* export const verificationTokens = pgTable("verificationToken", {
* identifier: text("identifier").notNull(),
* token: text("token").notNull(),
* expires: integer("expires").notNull()
* }, (vt) => ({
* _: primaryKey(vt.identifier, vt.token)
* }))
*
* const pool = new Pool({
* connectionString: "YOUR_CONNECTION_STRING"
* });
*
* export const db = drizzle(pool);
*
* migrate(db, { migrationsFolder: "./drizzle" })
*
* ```
*
**/
export function DrizzleAdapter(client: DrizzleClient): Adapter {
return {
createUser(data) {
return client
.insert(users)
.values({ ...data, id: "123" })
.returning()
.get()
},
getUser(data) {
return client.select().from(users).where(eq(users.id, data)).get() ?? null
},
getUserByEmail(data) {
return (
client.select().from(users).where(eq(users.email, data)).get() ?? null
)
},
createSession(data) {
return client.insert(sessions).values(data).returning().get()
},
getSessionAndUser(data) {
return (
client
.select({
session: sessions,
user: users,
})
.from(sessions)
.where(eq(sessions.sessionToken, data))
.innerJoin(users, eq(users.id, sessions.userId))
.get() ?? null
)
},
updateUser(data) {
if (!data.id) throw new Error("No user id.")
return client
.update(users)
.set(data)
.where(eq(users.id, data.id))
.returning()
.get()
},
updateSession(data) {
return client
.update(sessions)
.set(data)
.where(eq(sessions.sessionToken, data.sessionToken))
.returning()
.get()
},
linkAccount(rawAccount) {
const updatedAccount = client
.insert(accounts)
.values(rawAccount)
.returning()
.get()
// HACK: Should not need to set `undefined` values here
return {
...updatedAccount,
access_token: updatedAccount.access_token ?? undefined,
token_type: updatedAccount.token_type ?? undefined,
id_token: updatedAccount.id_token ?? undefined,
refresh_token: updatedAccount.refresh_token ?? undefined,
scope: updatedAccount.scope ?? undefined,
expires_at: updatedAccount.expires_at ?? undefined,
session_state: updatedAccount.session_state ?? undefined,
}
},
getUserByAccount(account) {
return (
client
.select()
.from(users)
.innerJoin(
accounts,
and(
eq(accounts.providerAccountId, account.providerAccountId),
eq(accounts.provider, account.provider)
)
)
.get()?.users ?? null
)
},
deleteSession(sessionToken) {
return client
.delete(sessions)
.where(eq(sessions.sessionToken, sessionToken))
.returning()
.get()
},
createVerificationToken(token) {
return client.insert(verificationTokens).values(token).returning().get()
},
useVerificationToken(token) {
try {
return (
client
.delete(verificationTokens)
.where(
and(
eq(verificationTokens.identifier, token.identifier),
eq(verificationTokens.token, token.token)
)
)
.returning()
.get() ?? null
)
} catch (err) {
throw new Error("No verification token found.")
}
},
deleteUser(id) {
return client.delete(users).where(eq(users.id, id)).returning().get()
},
unlinkAccount(account) {
client
.delete(accounts)
.where(
and(
eq(accounts.providerAccountId, account.providerAccountId),
eq(accounts.provider, account.provider)
)
)
.run()
// HACK: void should be fine
return undefined
},
}
}

View File

@@ -0,0 +1,63 @@
import { integer, sqliteTable, text, primaryKey } from "drizzle-orm/sqlite-core"
import { drizzle } from "drizzle-orm/better-sqlite3"
import { migrate } from "drizzle-orm/better-sqlite3/migrator"
import Database from "better-sqlite3"
import { ProviderType } from "next-auth/providers"
const sqlite = new Database("db.sqlite")
export const users = sqliteTable("users", {
id: text("id").notNull().primaryKey(),
name: text("name"),
email: text("email").notNull(),
emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
image: text("image"),
})
export const accounts = sqliteTable(
"accounts",
{
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
type: text("type").$type<ProviderType>().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
access_token: text("access_token"),
expires_at: integer("expires_at"),
token_type: text("token_type"),
scope: text("scope"),
id_token: text("id_token"),
session_state: text("session_state"),
},
(account) => ({
nameDoesntMatter: primaryKey(account.provider, account.providerAccountId),
})
)
export const sessions = sqliteTable("sessions", {
sessionToken: text("sessionToken").notNull().primaryKey(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
})
export const verificationTokens = sqliteTable(
"verificationToken",
{
identifier: text("identifier").notNull(),
token: text("token").notNull(),
expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
},
(vt) => ({
nameDoesntMatter: primaryKey(vt.identifier, vt.token),
})
)
export const db = drizzle(sqlite)
export type DrizzleClient = typeof db
migrate(db, { migrationsFolder: "./drizzle" })

View File

@@ -0,0 +1,68 @@
import { randomUUID, runBasicTests } from "@next-auth/adapter-test"
import { DrizzleAdapter } from "../src"
import { db, users, accounts, sessions, verificationTokens } from '../src/schema'
import { eq, and } from 'drizzle-orm/expressions';
runBasicTests({
adapter: DrizzleAdapter(db),
db: {
id() {
return randomUUID()
},
connect: async () => {
await Promise.all([
db.delete(sessions).run(),
db.delete(accounts).run(),
db.delete(verificationTokens).run(),
db.delete(users).run(),
])
},
disconnect: async () => {
await Promise.all([
db.delete(sessions).run(),
db.delete(accounts).run(),
db.delete(verificationTokens).run(),
db.delete(users).run(),
])
},
user: (id) => db
.select()
.from(users)
.where(eq(users.id, id))
.get() ?? null,
session: (sessionToken) => db
.select()
.from(sessions)
.where(eq(sessions.sessionToken, sessionToken))
.get() ?? null,
account: (provider_providerAccountId) => {
return db
.select()
.from(accounts)
.where(
eq(
accounts.providerAccountId,
provider_providerAccountId.providerAccountId
)
)
.get()
?? null
},
verificationToken: (identifier_token) => db
.select()
.from(verificationTokens)
.where(
and(
eq(
verificationTokens.token,
identifier_token.token
),
eq(
verificationTokens.identifier,
identifier_token.identifier
)
)
).get() ?? null,
},
})

View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": true,
"declarationMap": true,
"module": "ESNext",
"moduleResolution": "node",
"outDir": ".",
"rootDir": "src",
"skipDefaultLibCheck": true,
"skipLibCheck": true,
"strictNullChecks": true,
"stripInternal": true,
"target": "ES2020",
},
"exclude": [
"tests",
"*.js",
"*.d.ts*",
]
}

View File

@@ -9,10 +9,10 @@
* ## Installation
*
* ```bash npm2yarn2pnpm
* npm install next-auth @next-auth/dyanamodb-adapter
* npm install next-auth @next-auth/dynamodb-adapter
* ```
*
* @module @next-auth/dyanamodb-adapter
* @module @next-auth/dynamodb-adapter
*/
import { v4 as uuid } from "uuid"

View File

@@ -9,7 +9,7 @@
* ## Installation
*
* ```bash npm2yarn2pnpm
* npm install install next-auth @next-auth/sequelize-adapter sequelize
* npm install next-auth @next-auth/sequelize-adapter sequelize
* ```
*
* @module @next-auth/sequelize-adapter

View File

@@ -44,7 +44,7 @@ export interface AzureADB2CProfile {
* 2. [App Registration](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications)
* 3. [User Flow](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows)
*
* For the step "User attributes and token claims" you might want to set the following:
* For the step "User attributes and token claims" set the following:
*
* - Collect attribute:
* - Email Address

View File

@@ -39,7 +39,7 @@ export interface EmailConfig extends CommonProviderOptions {
* @default 86400
*/
maxAge?: number
/** [Documentation](https://authjs.dev/reference/providers/email#customizing-emails) */
/** [Documentation](https://authjs.dev/guides/providers/email#customizing-emails) */
sendVerificationRequest: (
params: SendVerificationRequestParams
) => Awaitable<void>
@@ -55,7 +55,7 @@ export interface EmailConfig extends CommonProviderOptions {
* }
* })
* ```
* [Documentation](https://authjs.dev/reference/providers/email#customizing-the-verification-token)
* [Documentation](https://authjs.dev/guides/providers/email#customizing-the-verification-token)
*/
generateVerificationToken?: () => Awaitable<string>
/** If defined, it is used to hash the verification token when saving to the database . */
@@ -72,7 +72,7 @@ export interface EmailConfig extends CommonProviderOptions {
* By default, we treat email addresses as all lower case,
* but you can override this function to change this behavior.
*
* [Documentation](https://authjs.dev/reference/providers/email#normalizing-the-e-mail-address) | [RFC 2821](https://tools.ietf.org/html/rfc2821) | [Email syntax](https://en.wikipedia.org/wiki/Email_address#Syntax)
* [Documentation](https://authjs.dev/guides/providers/email#normalizing-the-e-mail-address) | [RFC 2821](https://tools.ietf.org/html/rfc2821) | [Email syntax](https://en.wikipedia.org/wiki/Email_address#Syntax)
*/
normalizeIdentifier?: (identifier: string) => string
}

View File

@@ -150,6 +150,10 @@ export interface OAuth2Config<Profile>
checks?: Array<"pkce" | "state" | "none" | "nonce">
clientId?: string
clientSecret?: string
/**
* Pass overrides to the underlying OAuth library.
* See [`oauth4webapi` client](https://github.com/panva/oauth4webapi/blob/main/docs/interfaces/Client.md) for details.
*/
client?: Partial<Client>
style?: OAuthProviderButtonStyles
/**

View File

@@ -7,6 +7,11 @@ export default function Reddit(options) {
authorization: "https://www.reddit.com/api/v1/authorize?scope=identity",
token: "https://www.reddit.com/api/v1/access_token",
userinfo: "https://oauth.reddit.com/api/v1/me",
style: {
logo: "/reddit.svg",
bg: "#fff",
text: "#000",
},
options,
}
}

View File

@@ -1,23 +0,0 @@
/** @type {import(".").OAuthProvider} */
export default function Yandex(options) {
return {
id: "yandex",
name: "Yandex",
type: "oauth",
authorization:
"https://oauth.yandex.ru/authorize?scope=login:email+login:info",
token: "https://oauth.yandex.ru/token",
userinfo: "https://login.yandex.ru/info?format=json",
profile(profile) {
return {
id: profile.id,
name: profile.real_name,
email: profile.default_email,
image: profile.is_avatar_empty
? null
: `https://avatars.yandex.net/get-yapic/${profile.default_avatar_id}/islands-200`,
}
},
options,
}
}

View File

@@ -0,0 +1,155 @@
/**
* <div style={{backgroundColor: "#ffcc00", display: "flex", justifyContent: "space-between", color: "#000", padding: 16}}>
* <span>Built-in <b>Yandex</b> integration.</span>
* <a href="https://github.com">
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/yandex.svg" height="48" width="48"/>
* </a>
* </div>
*
* ---
* @module providers/yandex
*/
import { OAuthConfig, OAuthUserConfig } from "."
/**
* @see [Getting information about the user](https://yandex.com/dev/id/doc/en/user-information)
* @see [Access to email address](https://yandex.com/dev/id/doc/en/user-information#email-access)
* @see [Access to the user's profile picture](https://yandex.com/dev/id/doc/en/user-information#avatar-access)
* @see [Access to the date of birth](https://yandex.com/dev/id/doc/en/user-information#birthday-access)
* @see [Access to login, first name, last name, and gender](https://yandex.com/dev/id/doc/en/user-information#name-access)
* @see [Access to the phone number](https://yandex.com/dev/id/doc/en/user-information#phone-access)
*/
export interface YandexProfile {
/** User's Yandex login. */
login: string
/** Yandex user's unique ID. */
id: string
/**
* The ID of the app the OAuth token in the request was issued for.
* Available in the [app properties](https://oauth.yandex.com/). To open properties, click the app name.
*/
client_id: string
/** Authorized Yandex user ID. It is formed on the Yandex side based on the `client_id` and `user_id` pair. */
psuid: string
/** An array of the user's email addresses. Currently only includes the default email address. */
emails?: string[]
/** The default email address for contacting the user. */
default_email?: string
/**
* Indicates that the stub (profile picture that is automatically assigned when registering in Yandex)
* ID is specified in the `default_avatar_id` field.
*/
is_avatar_empty?: boolean
/**
* ID of the Yandex user's profile picture.
* The profile picture with this ID can be downloaded via a link that looks like this:
* @example "https://avatars.yandex.net/get-yapic/31804/BYkogAC6AoB17bN1HKRFAyKiM4-1/islands-200"
*/
default_avatar_id?:
| "islands-small"
| "islands-34"
| "islands-middle"
| "islands-50"
| "islands-retina-small"
| "islands-68"
| "islands-75"
| "islands-retina-middle"
| "islands-retina-50"
| "islands-200"
/**
* The user's date of birth in YYYY-MM-DD format.
* Unknown elements of the date are filled in with zeros, such as: `0000-12-23`.
* If the user's date of birth is unknow, birthday will be `null`
*/
birthday?: string | null
first_name?: string
last_name?: string
display_name?: string
/**
* The first and last name that the user specified in Yandex ID.
* Non-Latin characters of the first and last names are presented in Unicode format.
*/
real_name?: string
/** User's gender. Possible values: Male: `male', Female: `female`, Unknown gender: `null` */
sex?: string
/**
* The default phone number for contacting the user.
* The API can exclude the user's phone number from the response at its discretion.
* The field contains the following parameters:
* id: Phone number ID.
* number: The user's phone number.
*/
default_phone?: { id: number; number: string }
}
/**
* Add Yandex login to your page
*
* ## Example
*
* ```ts
* import { Auth } from "@auth/core"
* import Yandex from "@auth/core/providers/yandex"
*
* const request = new Request("https://example.com")
* const response = await Auth(request, {
* providers: [Yandex({ clientId: "", clientSecret: "" })],
* })
* ```
*
* ## Resources
*
* @see [Yandex - Creating an OAuth app](https://yandex.com/dev/id/doc/en/register-client#create)
* @see [Yandex - Manage OAuth apps](https://oauth.yandex.com/)
* @see [Yandex - OAuth documentation](https://yandex.com/dev/id/doc/en/)
* @see [Learn more about OAuth](https://authjs.dev/concepts/oauth)
* @see [Source code](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/yandex.ts)
*
*:::tip
* The Yandex provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/yandex.ts).
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
* :::
*
* :::info **Disclaimer**
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
*
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
* :::
*/
export default function Yandex(
options: OAuthUserConfig<YandexProfile>
): OAuthConfig<YandexProfile> {
return {
id: "yandex",
name: "Yandex",
type: "oauth",
/** @see [Data access](https://yandex.com/dev/id/doc/en/register-client#access) */
authorization:
"https://oauth.yandex.ru/authorize?scope=login:info+login:email+login:avatar",
token: "https://oauth.yandex.ru/token",
userinfo: "https://login.yandex.ru/info?format=json",
profile(profile) {
return {
id: profile.id,
name: profile.display_name ?? profile.real_name ?? profile.first_name,
email: profile.default_email ?? profile.emails?.[0] ?? null,
image:
!profile.is_avatar_empty && profile.default_avatar_id
? `https://avatars.yandex.net/get-yapic/${profile.default_avatar_id}/islands-200`
: null,
}
},
style: {
logo: "/yandex.svg",
logoDark: "/yandex.svg",
bg: "#ffcc00",
text: "#000",
bgDark: "#ffcc00",
textDark: "#000",
},
options,
}
}

View File

@@ -5,7 +5,7 @@ export default function Reddit(options) {
name: "Reddit",
type: "oauth",
authorization: "https://www.reddit.com/api/v1/authorize?scope=identity",
token: " https://www.reddit.com/api/v1/access_token",
token: "https://www.reddit.com/api/v1/access_token",
userinfo: "https://oauth.reddit.com/api/v1/me",
profile(profile) {
return {
@@ -15,6 +15,11 @@ export default function Reddit(options) {
image: null,
}
},
style: {
logo: "https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos/reddit.svg",
bg: "#fff",
text: "#000",
},
options,
}
}

1299
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -51,7 +51,26 @@
"env": ["UPSTASH_REDIS_KEY", "UPSTASH_REDIS_URL"]
},
"docs#dev": {
"dependsOn": ["^build"],
"dependsOn": [
"@auth/core#build",
"@auth/sveltekit#build",
"@next-auth/dgraph-adapter#build",
"@next-auth/dynamodb-adapter#build",
"@next-auth/fauna-adapter#build",
"@next-auth/firebase-adapter#build",
"@next-auth/mikro-orm-adapter#build",
"@next-auth/mongodb-adapter#build",
"@next-auth/neo4j-adapter#build",
"@next-auth/pouchdb-adapter#build",
"@next-auth/prisma-adapter#build",
"@next-auth/sequelize-adapter#build",
"@next-auth/supabase-adapter#build",
"@next-auth/typeorm-legacy-adapter#build",
"@next-auth/upstash-redis-adapter#build",
"@next-auth/xata-adapter#build",
"^build",
"next-auth#build"
],
"cache": false
},
"docs#build": {
@@ -72,6 +91,7 @@
"@next-auth/typeorm-legacy-adapter#build",
"@next-auth/upstash-redis-adapter#build",
"@next-auth/xata-adapter#build",
"^build",
"next-auth#build"
],
"outputs": [