mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
35 Commits
docs/remov
...
feat/drizz
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b72eabb15d | ||
|
|
371f7bd4a1 | ||
|
|
35f71bbcc8 | ||
|
|
97b1202ecb | ||
|
|
8423a05e95 | ||
|
|
6c07331cc5 | ||
|
|
c8ef94b2be | ||
|
|
75a59fbd92 | ||
|
|
3dd47b0735 | ||
|
|
4dc1d421f8 | ||
|
|
99ca67f1cf | ||
|
|
a087df8494 | ||
|
|
1aa4994de6 | ||
|
|
88023f69b9 | ||
|
|
b02057a72d | ||
|
|
400da8c766 | ||
|
|
b48104801b | ||
|
|
ccbbc800d2 | ||
|
|
d7888263ca | ||
|
|
47d3151410 | ||
|
|
7d264860ab | ||
|
|
6184b936f5 | ||
|
|
1954258a0a | ||
|
|
c580f0db22 | ||
|
|
d1cf701ed9 | ||
|
|
69398e2d3a | ||
|
|
856b5c50fc | ||
|
|
2830b7de5b | ||
|
|
40a0faa586 | ||
|
|
a6b4d958ac | ||
|
|
cc13df9d51 | ||
|
|
06b8d4772c | ||
|
|
d644d1fcbf | ||
|
|
380f2de961 | ||
|
|
dc5f3e1873 |
@@ -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*
|
||||
75
.eslintrc.js
75
.eslintrc.js
@@ -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
1
.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 }),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -174,7 +174,7 @@ If you are deploying directly to a particular cloud platform you may also want t
|
||||
|
||||
## Security
|
||||
|
||||
Parts of this section has been moved to its [own page](/getting-started/security).
|
||||
Parts of this section has been moved to its [own page](/security).
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -128,7 +128,7 @@ import { useSession, signIn, signOut } from "next-auth/react"
|
||||
|
||||
export default function CamperVanPage() {
|
||||
const { data: session, status } = useSession()
|
||||
const userEmail = session?.user.email
|
||||
const userEmail = session?.user?.email
|
||||
|
||||
if (status === "loading") {
|
||||
return <p>Hang on there...</p>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -10,4 +10,4 @@ When using a database, you can still use JWT for session handling for fast acces
|
||||
|
||||
We have a list of official adapters that are distributed as their own packages under the `@next-auth/{name}-adapter` namespace. Their source code is available in their various adapters package directories at [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth/tree/main/packages):
|
||||
|
||||
- [All available adapters](/reference/adapters/overview)
|
||||
- [All available adapters](/reference/adapters)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"label": "Basics",
|
||||
"collapsible": true,
|
||||
"collapsed": true
|
||||
"collapsed": false
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
---
|
||||
title: Overview
|
||||
sidebar_label: Guides
|
||||
sidebar_position: 0
|
||||
---
|
||||
|
||||
We're creating internal guides to help understand how to use Auth.js and all the possible configurations and uses cases it supports.
|
||||
This section contains guides for common use cases.
|
||||
|
||||
If you can't find what you're looking for, [raise an issue](https://github.com/nextauthjs/next-auth/issues/new/choose) then take a look at our third-party [community resources](/guides/resources).
|
||||
If you can't find what you're looking for, [raise an issue](https://github.com/nextauthjs/next-auth/issues/new?assignees=&labels=triage%2Cdocumentation&template=4_documentation.yml).
|
||||
|
||||
:::warning Warning
|
||||
Guides are being migrated from the [old documentation page](https://next-auth.js.org), so there are going to be references to `next-auth` still. We are continuously working on updating the naming/references.
|
||||
:::
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"label": "Other",
|
||||
"collapsible": true,
|
||||
"collapsed": true
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
---
|
||||
title: LDAP Authentication
|
||||
---
|
||||
|
||||
Auth.js provides the ability to setup a [custom Credential provider](/guides/providers/credentials) which we can take advantage of to authenticate users against an existing LDAP server.
|
||||
|
||||
You will need an additional dependency, `ldapjs`, which you can install by running
|
||||
|
||||
```bash npm2yarn2pnpm
|
||||
npm install ldapjs
|
||||
```
|
||||
|
||||
Then you must setup the `CredentialsProvider()` provider key like so:
|
||||
|
||||
```js title="[...nextauth].js"
|
||||
const ldap = require("ldapjs")
|
||||
import NextAuth from "next-auth"
|
||||
import CredentialsProvider from "next-auth/providers/credentials"
|
||||
|
||||
export default NextAuth({
|
||||
providers: [
|
||||
CredentialsProvider({
|
||||
name: "LDAP",
|
||||
credentials: {
|
||||
username: { label: "DN", type: "text", placeholder: "" },
|
||||
password: { label: "Password", type: "password" },
|
||||
},
|
||||
async authorize(credentials, req) {
|
||||
// You might want to pull this call out so we're not making a new LDAP client on every login attempt
|
||||
const client = ldap.createClient({
|
||||
url: process.env.LDAP_URI,
|
||||
})
|
||||
|
||||
// Essentially promisify the LDAPJS client.bind function
|
||||
return new Promise((resolve, reject) => {
|
||||
client.bind(credentials.username, credentials.password, (error) => {
|
||||
if (error) {
|
||||
console.error("Failed")
|
||||
reject()
|
||||
} else {
|
||||
console.log("Logged in")
|
||||
resolve({
|
||||
username: credentials.username,
|
||||
password: credentials.password,
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
}),
|
||||
],
|
||||
callbacks: {
|
||||
async jwt({ token, user }) {
|
||||
const isSignIn = user ? true : false
|
||||
if (isSignIn) {
|
||||
token.username = user.username
|
||||
token.password = user.password
|
||||
}
|
||||
return token
|
||||
},
|
||||
async session({ session, token }) {
|
||||
return { ...session, user: { username: token.username } }
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
The idea is that once one is authenticated with the LDAP server, one can pass through both the username/DN and password to the JWT stored in the browser.
|
||||
|
||||
This is then passed back to any API routes and retrieved as such:
|
||||
|
||||
```js title="/pages/api/doLDAPWork.js"
|
||||
token = await jwt.getToken({
|
||||
req,
|
||||
})
|
||||
const { username, password } = token
|
||||
```
|
||||
|
||||
> Thanks to [Winwardo](https://github.com/Winwardo) for the code example
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
title: Usage with class components
|
||||
---
|
||||
|
||||
If you want to use the [`useSession()`](/reference/react/#usesession) hook in your class components you can do so with the help of a higher order component or with a render prop.
|
||||
|
||||
## Higher Order Component
|
||||
|
||||
```js
|
||||
import { useSession } from "next-auth/react"
|
||||
|
||||
const withSession = (Component) => (props) => {
|
||||
const session = useSession()
|
||||
|
||||
// if the component has a render property, we are good
|
||||
if (Component.prototype.render) {
|
||||
return <Component session={session} {...props} />
|
||||
}
|
||||
|
||||
// if the passed component is a function component, there is no need for this wrapper
|
||||
throw new Error(
|
||||
[
|
||||
"You passed a function component, `withSession` is not needed.",
|
||||
"You can `useSession` directly in your component.",
|
||||
].join("\n")
|
||||
)
|
||||
}
|
||||
|
||||
// Usage
|
||||
class ClassComponent extends React.Component {
|
||||
render() {
|
||||
const { data: session, status } = this.props.session
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const ClassComponentWithSession = withSession(ClassComponent)
|
||||
```
|
||||
|
||||
## Render Prop
|
||||
|
||||
```js
|
||||
import { useSession } from "next-auth/react"
|
||||
|
||||
const UseSession = ({ children }) => {
|
||||
const session = useSession()
|
||||
return children(session)
|
||||
}
|
||||
|
||||
// Usage
|
||||
class ClassComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<UseSession>
|
||||
{(session) => <pre>{JSON.stringify(session, null, 2)}</pre>}
|
||||
</UseSession>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -3,21 +3,21 @@ id: credentials
|
||||
title: Credentials Provider
|
||||
---
|
||||
|
||||
The Credentials provider allows you to handle signing in with arbitrary credentials, such as a username and password, domain, or two factor authentication or hardware device (e.g. YubiKey U2F / FIDO).
|
||||
The Credentials provider allows you to handle signing in with arbitrary credentials, such as a username and password, domain, or two-factor authentication or hardware device (e.g. YubiKey U2F / FIDO).
|
||||
|
||||
It is intended to support use cases where you have an existing system you need to authenticate users against.
|
||||
|
||||
It comes with the constraint that users authenticated in this manner are not persisted in the database, and consequently that the Credentials provider can only be used if JSON Web Tokens are enabled for sessions.
|
||||
|
||||
:::warning
|
||||
The functionality provided for credentials based authentication is intentionally limited to discourage use of passwords due to the inherent security risks associated with them and the additional complexity associated with supporting usernames and passwords.
|
||||
The functionality provided for credentials-based authentication is intentionally limited to discourage the use of passwords due to the inherent security risks associated with them and the additional complexity associated with supporting usernames and passwords.
|
||||
:::
|
||||
|
||||
## Options
|
||||
|
||||
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.
|
||||
|
||||
@@ -33,7 +33,7 @@ If you return an object it will be persisted to the JSON Web Token and the user
|
||||
|
||||
3. If you throw an Error, the user will be sent to the error page with the error message as a query parameter.
|
||||
|
||||
The Credentials provider's `authorize()` method also provides the request object as the second parameter (see example below).
|
||||
The Credentials provider's `authorize()` method also provides the request object as the second parameter (see the example below).
|
||||
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import CredentialsProvider from "next-auth/providers/credentials";
|
||||
@@ -89,7 +89,7 @@ You can specify more than one credentials provider by specifying a unique `id` f
|
||||
|
||||
You can also use them in conjunction with other provider options.
|
||||
|
||||
As with all providers, the order you specify them is the order they are displayed on the sign in page.
|
||||
As with all providers, the order you specify is the order they are displayed on the sign-in page.
|
||||
|
||||
```js
|
||||
providers: [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Customized OAuth Provider
|
||||
title: OAuth Provider
|
||||
---
|
||||
|
||||
Auth.js comes with a set of built-in OAuth providers that you can import from `@auth/core/providers/*`. Every provider has their separate documentation page under the [core package's API Reference](/reference/core)
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
32
docs/docs/reference/index.md
Normal file
32
docs/docs/reference/index.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Overview
|
||||
---
|
||||
|
||||
This section of the documentation contains the API reference for all the official packages under the `@auth/*` and `@next-auth/*` scopes.
|
||||
|
||||
:::warning Warning
|
||||
The API reference is being migrated from the [old documentation page](https://next-auth.js.org), so there are going to be references to `next-auth` still. We are continuously working on updating the naming/references.
|
||||
:::
|
||||
|
||||
## Roadmap
|
||||
|
||||
Here are the _currently_ planned and released packages under the `@auth/*` scope. This is not an exhaustive list, but the set of packages that we would like to focus on to begin with.
|
||||
|
||||
| Feature | Status |
|
||||
| ------------------- | -------- |
|
||||
| `@auth/nextjs` | Planned |
|
||||
| `@auth/*-adapter` | Planned |
|
||||
| `@auth/core` | Experimental |
|
||||
| `@auth/sveltekit` | Experimental |
|
||||
| `@auth/solid-start` | Experimental |
|
||||
|
||||
### Community Packages
|
||||
|
||||
While we are migrating the documentation and working on stabilizing the core package, the community has been working on some packages that are already available. With collaboration, we hope to make these packages official in the future.
|
||||
|
||||
:::note
|
||||
If you are a maintainer of a package, [reach out](https://twitter.com/balazsorban44) if you want to collaborate on making it official or open a PR to add it to the list below, so others can discover it more easily.
|
||||
:::
|
||||
|
||||
- ...
|
||||
- ...
|
||||
@@ -2,6 +2,16 @@
|
||||
title: Security
|
||||
---
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Security updates are only released for the current version.
|
||||
|
||||
Old releases are not maintained and do not receive updates.
|
||||
|
||||
:::caution
|
||||
`@auth/*` packages are currently under development and - unless stated otherwise - they are not considered ready for production yet. That said, we encourage you to reach out to us if you have any questions or concerns via the below-mentioned channels. We are committed to making Auth.js a secure and reliable solution for your authentication needs.
|
||||
:::
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Auth.js practices responsible disclosure.
|
||||
@@ -13,16 +23,11 @@ If you contact us regarding a serious issue:
|
||||
- We will endeavor to get back to you within 72 hours.
|
||||
- We will aim to publish a fix within 30 days.
|
||||
- We will disclose the issue (and credit you, with your consent) once a fix to resolve the issue has been released.
|
||||
- If 90 days has elapsed and we still don't have a fix, we will disclose the issue publicly.
|
||||
- If 90 days have elapsed and we still don't have a fix, we will disclose the issue publicly.
|
||||
|
||||
The best way to report an issue is by contacting us via email at info@balazsorban.com or me@iaincollins.com and yo@ndo.dev, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
|
||||
The best way to report an issue is by contacting us via email at info@balazsorban.com, hi@thvu.dev and yo@ndo.dev, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
|
||||
|
||||
:::note
|
||||
For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to make these public as bug reports or feature requests or to raise a question to open a discussion around them.
|
||||
:::
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Security updates are only released for the current version.
|
||||
|
||||
Old releases are not maintained and do not receive updates.
|
||||
@@ -93,11 +93,9 @@ const docusaurusConfig = {
|
||||
position: "left",
|
||||
},
|
||||
{
|
||||
to: "/reference/core",
|
||||
// TODO: change to this when the overview page looks better.
|
||||
// to: "/reference",
|
||||
to: "/reference",
|
||||
activeBasePath: "/reference",
|
||||
label: "Reference",
|
||||
label: "API Reference",
|
||||
position: "left",
|
||||
},
|
||||
{
|
||||
@@ -106,6 +104,12 @@ const docusaurusConfig = {
|
||||
label: "Concepts",
|
||||
position: "left",
|
||||
},
|
||||
{
|
||||
to: "/security",
|
||||
activeBasePath: "/security",
|
||||
label: "Security",
|
||||
position: "left",
|
||||
},
|
||||
{
|
||||
type: "docsVersionDropdown",
|
||||
position: "right",
|
||||
@@ -132,7 +136,7 @@ const docusaurusConfig = {
|
||||
announcementBar: {
|
||||
id: "new-major-announcement",
|
||||
content:
|
||||
"<a target='_blank' rel='noopener noreferrer' href='https://next-auth.js.org'>NextAuth.js</a> is becoming Auth.js! 🎉 We're creating Authentication for the Web. Everyone included. Starting with SvelteKit, check out <a href='/reference/sveltekit'>the docs</a>. Note, this site is under active development.",
|
||||
"<a target='_blank' rel='noopener noreferrer' href='https://next-auth.js.org'>NextAuth.js</a> is becoming Auth.js! 🎉 <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/balazsorban44/status/1603082914362986496'>Read the announcement.</a> Note, this site is under active development. 🏗",
|
||||
backgroundColor: "#000",
|
||||
textColor: "#fff",
|
||||
},
|
||||
@@ -258,6 +262,7 @@ const docusaurusConfig = {
|
||||
},
|
||||
],
|
||||
typedocAdapter("Dgraph"),
|
||||
typedocAdapter("Drizzle ORM"),
|
||||
typedocAdapter("DynamoDB"),
|
||||
typedocAdapter("Fauna"),
|
||||
typedocAdapter("Firebase"),
|
||||
|
||||
@@ -14,6 +14,7 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
referenceSidebar: [
|
||||
"reference/index",
|
||||
{
|
||||
type: "category",
|
||||
label: "@auth/core",
|
||||
@@ -52,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" },
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -104,7 +104,7 @@ html[data-theme="dark"] hr {
|
||||
|
||||
/* Docusaurus announcementBar close button */
|
||||
.close {
|
||||
color: inherit;
|
||||
color: inherit!important;
|
||||
}
|
||||
|
||||
.home-main .code {
|
||||
|
||||
@@ -135,7 +135,7 @@ export default function Home() {
|
||||
)}
|
||||
href="https://next-auth-example.vercel.app"
|
||||
>
|
||||
Live Demo (Next.js)
|
||||
Next.js Demo
|
||||
</a>
|
||||
<a
|
||||
className={classnames(
|
||||
@@ -144,7 +144,7 @@ export default function Home() {
|
||||
)}
|
||||
href="https://sveltekit-auth-example.vercel.app"
|
||||
>
|
||||
Live Demo (SvelteKit)
|
||||
SvelteKit Demo
|
||||
</a>
|
||||
<a
|
||||
className={classnames(
|
||||
@@ -153,7 +153,7 @@ export default function Home() {
|
||||
)}
|
||||
href="https://auth-solid.vercel.app"
|
||||
>
|
||||
Live Demo (SolidStart)
|
||||
SolidStart Demo
|
||||
</a>
|
||||
<Link
|
||||
className={classnames(
|
||||
|
||||
BIN
docs/static/img/adapters/drizzle-orm.png
vendored
Normal file
BIN
docs/static/img/adapters/drizzle-orm.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
6
docs/static/img/providers/reddit.svg
vendored
Normal file
6
docs/static/img/providers/reddit.svg
vendored
Normal 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
1
docs/static/img/providers/yandex.svg
vendored
Normal 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 |
202
package.json
202
package.json
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
28
packages/adapter-drizzle/README.md
Normal file
28
packages/adapter-drizzle/README.md
Normal 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).
|
||||
57
packages/adapter-drizzle/package.json
Normal file
57
packages/adapter-drizzle/package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
248
packages/adapter-drizzle/src/index.ts
Normal file
248
packages/adapter-drizzle/src/index.ts
Normal 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
|
||||
},
|
||||
}
|
||||
}
|
||||
63
packages/adapter-drizzle/src/schema.ts
Normal file
63
packages/adapter-drizzle/src/schema.ts
Normal 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" })
|
||||
68
packages/adapter-drizzle/tests/index.test.ts
Normal file
68
packages/adapter-drizzle/tests/index.test.ts
Normal 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,
|
||||
},
|
||||
})
|
||||
21
packages/adapter-drizzle/tsconfig.json
Normal file
21
packages/adapter-drizzle/tsconfig.json
Normal 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*",
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
155
packages/core/src/providers/yandex.ts
Normal file
155
packages/core/src/providers/yandex.ts
Normal 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,
|
||||
}
|
||||
}
|
||||
@@ -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
1299
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
22
turbo.json
22
turbo.json
@@ -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": [
|
||||
|
||||
Reference in New Issue
Block a user