Compare commits

..

10 Commits

Author SHA1 Message Date
Amauri Dias
d1dbfe1023 fix: truly replace .flat() to support Node <11 again (#1691) 2021-04-11 23:20:37 +02:00
David Colón
63171a0271 fix: validate provider existence before looking for protection property (#1687)
* Fix validation of provider existence before looking for protection property

* Use optional chaining
2021-04-11 15:20:01 +02:00
Amauri Dias
872e180339 fix: replace .flat() to support Node <11 again (#1684) 2021-04-11 10:57:25 +02:00
ifly7charlie
a7709df796 docs: Document the additional parameters in JWT (#1550)
Co-authored-by: Balázs Orbán <info@balazsorban.com>
2021-04-08 14:00:19 +02:00
Balázs Orbán
dbe283f0fa refactor: rename extend-res to extend-req 2021-04-07 22:26:54 +02:00
Balázs Orbán
727426bbec chore(ts): auto-label TypeScript related changes 2021-04-07 20:16:10 +02:00
Vinicius CR
5a3ee47337 feat(provider): accept array for protection to support multiple mechanisms (#1565)
* fix: add protection both option

* feat: update docs with new protection value

* fix: lint files

* refactor: change protection from string to array

* chore: reverting unespected change

* chore: lint files

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2021-04-06 19:20:56 +02:00
bhaveshmishra-code
8dd8f7c48a docs: fix typo in callbacks.md (#1657)
Fixed the spelling mistake.

existance -> existence
2021-04-05 19:35:26 +02:00
Jaime Martínez Rincón
072c59d85a docs: fix typo primsa (#1652) 2021-04-05 00:25:46 +02:00
dependabot[bot]
d0e8147a48 chore(deps): bump y18n from 4.0.0 to 4.0.1 (#1631)
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-04-05 00:24:39 +02:00
36 changed files with 685 additions and 28139 deletions

6
.github/labeler.yml vendored
View File

@@ -1,5 +1,6 @@
test:
- test/**/*
- types/tests/**/*
documentation:
- www/**/*
@@ -32,4 +33,7 @@ client:
pages:
- src/server/pages/**/*
- www/docs/configuration/pages.md
- www/docs/configuration/pages.md
TypeScript:
- types/**/*

View File

@@ -6,12 +6,10 @@ on:
push:
branches:
- main
- beta
- next
pull_request:
branches:
- main
- beta
- next
jobs:

View File

@@ -13,7 +13,7 @@ name: "CodeQL"
on:
push:
branches: [ main, beta, next ]
branches: [ main, next ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]

View File

@@ -2,10 +2,9 @@ name: Integration Test
on:
push:
branches:
- main
- beta
- next
branches:
- main
- next
pull_request:
jobs:
@@ -18,7 +17,7 @@ jobs:
if: github.event.pull_request.head.repo.full_name == github.repository
# We use self-hosted runners as cloud based runnners (e.g. AWS, GPC)
# fail due to IP Address checks done by providers, which enforce
# fail due to IP Address checks done by providers, which enforce
# CAPTCHA checks on login request from cloud compute IP addresses to
# prevent abuse.
runs-on: self-hosted
@@ -46,7 +45,7 @@ jobs:
- run: npm test
# TODO Tests should exit out if env vars not set (currently hangs)
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
NEXTAUTH_TWITTER_ID: ${{secrets.NEXTAUTH_TWITTER_ID}}
NEXTAUTH_TWITTER_SECRET: ${{secrets.NEXTAUTH_TWITTER_SECRET}}
NEXTAUTH_TWITTER_USERNAME: ${{secrets.NEXTAUTH_TWITTER_USERNAME}}

View File

@@ -3,7 +3,6 @@ on:
push:
branches:
- 'main'
- 'beta'
- 'next'
- '3.x'
pull_request:

View File

@@ -1,25 +0,0 @@
name: Types
on:
push:
branches:
- main
- beta
- next
pull_request:
branches:
- main
- beta
- next
jobs:
lint-and-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
- name: Install dependencies
uses: bahmutov/npm-install@v1
- name: Check types
run: npm run test:types

View File

@@ -1,3 +0,0 @@
./types/tests/
./types/tests/tsconfig.json
./types/tests/tslint.json

View File

@@ -1,3 +0,0 @@
{
"semi": false
}

View File

@@ -1,23 +0,0 @@
const fs = require('fs')
const path = require('path')
const BUILD_TARGETS = [
'index.d.ts',
'client.d.ts',
'adapters.d.ts',
'providers.d.ts',
'jwt.d.ts',
'_next.d.ts',
'_utils.d.ts'
]
BUILD_TARGETS.forEach((target) => {
fs.copyFile(
path.resolve('types', target),
path.join(process.cwd(), target),
(err) => {
if (err) throw err
console.log(`[build-types] copying "${target}" to root folder`)
}
)
})

26937
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,10 +7,9 @@
"author": "Iain Collins <me@iaincollins.com>",
"main": "index.js",
"scripts": {
"build": "npm run build:js && npm run build:css && npm run build:types",
"build": "npm run build:js && npm run build:css",
"build:js": "babel --config-file ./config/babel.config.json src --out-dir dist",
"build:css": "postcss --config config/postcss.config.js src/**/*.css --base src --dir dist && node config/wrap-css.js",
"build:types": "node ./config/build-types.js",
"dev": "next | npm run watch:css",
"watch": "npm run watch:js | npm run watch:css",
"watch:js": "babel --config-file ./config/babel.config.json --watch src --out-dir dist",
@@ -18,14 +17,13 @@
"test:app:start": "docker-compose -f test/docker/app.yml up -d",
"test:app:rebuild": "npm run build && docker-compose -f test/docker/app.yml up -d --build",
"test:app:stop": "docker-compose -f test/docker/app.yml down",
"test": "npm run test:app:rebuild && npm run test:integration && npm run test:app:stop && npm run test:types",
"test": "npm run test:app:rebuild && npm run test:integration && npm run test:app:stop",
"test:db": "npm run test:db:mysql && npm run test:db:postgres && npm run test:db:mongodb && npm run test:db:mssql",
"test:db:mysql": "node test/mysql.js",
"test:db:postgres": "node test/postgres.js",
"test:db:mongodb": "node test/mongodb.js",
"test:db:mssql": "node test/mssql.js",
"test:integration": "mocha test/integration",
"test:types": "dtslint types",
"db:start": "docker-compose -f test/docker/databases.yml up -d",
"db:stop": "docker-compose -f test/docker/databases.yml down",
"prepublishOnly": "npm run build",
@@ -34,10 +32,8 @@
"lint": "ts-standard",
"lint:fix": "ts-standard --fix"
},
"types": "types",
"files": [
"dist",
"types",
"index.js",
"providers.js",
"adapters.js",
@@ -61,7 +57,7 @@
},
"peerDependencies": {
"react": "^16.13.1 || ^17",
"react-dom": "16.13.1 || ^17"
"react-dom": "^16.13.1 || ^17"
},
"peerOptionalDependencies": {
"mongodb": "^3.5.9",
@@ -85,7 +81,6 @@
"conventional-changelog-conventionalcommits": "4.4.0",
"cssnano": "^4.1.10",
"dotenv": "^8.2.0",
"dtslint": "^4.0.8",
"eslint": "^7.19.0",
"mocha": "^8.1.3",
"mongodb": "^3.5.9",
@@ -95,7 +90,6 @@
"pg": "^8.2.1",
"postcss-cli": "^7.1.1",
"postcss-nested": "^4.2.1",
"prettier": "^2.2.1",
"prisma": "^2.16.1",
"puppeteer": "^5.2.1",
"puppeteer-extra": "^3.1.15",
@@ -109,8 +103,7 @@
"project": "./tsconfig.json",
"ignore": [
"test/",
"next-env.d.ts",
"types/"
"next-env.d.ts"
],
"globals": [
"localStorage",

View File

@@ -2,7 +2,6 @@ module.exports = {
branches: [
'+([0-9])?(.{+([0-9]),x}).x',
'main',
{ name: 'beta', prerelease: true },
{ name: 'next', prerelease: true }
]
}

View File

@@ -7,7 +7,7 @@ import * as defaultEvents from './lib/default-events'
import * as defaultCallbacks from './lib/default-callbacks'
import parseProviders from './lib/providers'
import callbackUrlHandler from './lib/callback-url-handler'
import extendRes from './lib/extend-req'
import extendRes from './lib/extend-res'
import * as routes from './routes'
import renderPage from './pages'
import csrfTokenHandler from './lib/csrf-token-handler'
@@ -79,6 +79,10 @@ async function NextAuthHandler (req, res, userOptions) {
provider.protection = 'state' // Default to state, as we did in 3.1 REVIEW: should we use "pkce" or "none" as default?
}
if (typeof provider?.protection === 'string') {
provider.protection = [provider.protection]
}
const maxAge = 30 * 24 * 60 * 60 // Sessions expire after 30 days of being idle
// Parse database / adapter

View File

@@ -136,7 +136,7 @@ async function getOAuth2AccessToken (code, provider, codeVerifier) {
headers.Authorization = `Bearer ${code}`
}
if (provider.protection === 'pkce') {
if (provider.protection.includes('pkce')) {
params.code_verifier = codeVerifier
}

View File

@@ -16,7 +16,7 @@ const PKCE_MAX_AGE = 60 * 15 // 15 minutes in seconds
export async function handleCallback (req, res) {
const { cookies, provider, baseUrl, basePath } = req.options
try {
if (provider.protection !== 'pkce') { // Provider does not support PKCE, nothing to do.
if (!provider.protection.includes('pkce')) { // Provider does not support PKCE, nothing to do.
return
}
@@ -50,7 +50,7 @@ export async function handleCallback (req, res) {
export async function handleSignin (req, res) {
const { cookies, provider, baseUrl, basePath } = req.options
try {
if (provider.protection !== 'pkce') { // Provider does not support PKCE, nothing to do.
if (!provider.protection.includes('pkce')) { // Provider does not support PKCE, nothing to do.
return
}
// Started login flow, add generated pkce to req.options and (encrypted) code_verifier to a cookie

View File

@@ -12,7 +12,7 @@ import { OAuthCallbackError } from '../../../lib/errors'
export async function handleCallback (req, res) {
const { csrfToken, provider, baseUrl, basePath } = req.options
try {
if (provider.protection !== 'state') { // Provider does not support state, nothing to do.
if (!provider.protection.includes('state')) { // Provider does not support state, nothing to do.
return
}
@@ -41,7 +41,7 @@ export async function handleCallback (req, res) {
export async function handleSignin (req, res) {
const { provider, baseUrl, basePath, csrfToken } = req.options
try {
if (provider.protection !== 'state') { // Provider does not support state, nothing to do.
if (!provider.protection.includes('state')) { // Provider does not support state, nothing to do.
return
}

40
types/_next.d.ts vendored
View File

@@ -1,40 +0,0 @@
import { IncomingMessage, ServerResponse } from "http"
// ------------------------------------------------------
// Types from next@10,
// see: https://github.com/microsoft/dtslint/issues/297
// ------------------------------------------------------
export interface NextApiRequest extends IncomingMessage {
query: {
[key: string]: string | string[]
}
cookies: {
[key: string]: string
}
body: any
env: any
preview?: boolean
previewData?: any
}
export type Send<T> = (body: T) => void
export type NextApiResponse<T = any> = ServerResponse & {
send: Send<T>
json: Send<T>
status: (statusCode: number) => NextApiResponse<T>
redirect: ((url: string) => NextApiResponse<T>) &
((status: number, url: string) => NextApiResponse<T>)
setPreviewData: (
data: object | string,
options?: {
maxAge?: number
}
) => NextApiResponse<T>
clearPreviewData: () => NextApiResponse<T>
}
export type NextApiHandler<T = any> = (
req: NextApiRequest,
res: NextApiResponse<T>
) => void | Promise<void>

12
types/_utils.d.ts vendored
View File

@@ -1,12 +0,0 @@
export type NonNullParams<T> = {
[K in keyof T]: T[K] extends Record<string, unknown>
? NonNullParams<T[K]>
: NonNullable<T[K]>
}
export type NullableParams<T> = {
[K in keyof T]: T[K] | undefined | null
}
export type WithAdditionalParams<T extends Record<string, any>> = T &
Record<string, unknown>

242
types/adapters.d.ts vendored
View File

@@ -1,242 +0,0 @@
import { ConnectionOptions, EntitySchema } from "typeorm"
import { AppOptions, User } from "."
import { AppProvider } from "./providers"
export interface Profile {
id: string
name: string
email: string | null
image?: string | null
}
export interface Session {
userId: string | number | object
expires: Date
sessionToken: string
accessToken: string
}
export interface VerificationRequest {
identifier: string
token: string
expires: Date
}
export interface SendVerificationRequestParams {
identifier: string
url: string
token: string
baseUrl: string
provider: AppProvider
}
export type EmailAppProvider = AppProvider & {
sendVerificationRequest: (
params: SendVerificationRequestParams
) => Promise<void>
maxAge: number | undefined
}
export interface AdapterInstance<
TUser,
TProfile,
TSession,
TVerificationRequest
> {
createUser: (profile: TProfile) => Promise<TUser>
getUser: (id: string) => Promise<TUser | null>
getUserByEmail: (email: string) => Promise<TUser | null>
getUserByProviderAccountId: (
providerId: string,
providerAccountId: string
) => Promise<TUser | null>
updateUser: (user: TUser) => Promise<TUser>
linkAccount: (
userId: string,
providerId: string,
providerType: string,
providerAccountId: string,
refreshToken: string,
accessToken: string,
accessTokenExpires: number
) => Promise<void>
createSession: (user: TUser) => Promise<TSession>
getSession: (sessionToken: string) => Promise<TSession | null>
updateSession: (session: TSession, force?: boolean) => Promise<TSession>
deleteSession: (sessionToken: string) => Promise<void>
createVerificationRequest?: (
email: string,
url: string,
token: string,
secret: string,
provider: EmailAppProvider,
options: AppOptions
) => Promise<TVerificationRequest>
getVerificationRequest?: (
email: string,
verificationToken: string,
secret: string,
provider: AppProvider
) => Promise<TVerificationRequest | null>
deleteVerificationRequest?: (
email: string,
verificationToken: string,
secret: string,
provider: AppProvider
) => Promise<void>
}
interface Adapter<
TUser extends User = any,
TProfile extends Profile = any,
TSession extends Session = any,
TVerificationRequest extends VerificationRequest = any
> {
getAdapter: (
appOptions: AppOptions
) => Promise<AdapterInstance<TUser, TProfile, TSession, TVerificationRequest>>
}
type Schema<T = any> = EntitySchema<T>["options"]
interface Adapters {
Default: TypeORMAdapter["Adapter"]
TypeORM: TypeORMAdapter
Prisma: PrismaAdapter
}
/**
* TODO: fix auto-type schema
*/
interface TypeORMAdapter<
A extends TypeORMAccountModel = any,
U extends TypeORMUserModel = any,
S extends TypeORMSessionModel = any,
VR extends TypeORMVerificationRequestModel = any
> {
Adapter: (
typeOrmConfig: ConnectionOptions,
options?: {
models?: {
Account?: {
model: A
schema: Schema<A>
}
User?: {
model: U
schema: Schema<U>
}
Session?: {
model: S
schema: Schema<S>
}
VerificationRequest?: {
model: VR
schema: Schema<VR>
}
}
}
) => Adapter<U, Profile, S, VR>
Models: {
Account: {
model: TypeORMAccountModel
schema: Schema<TypeORMAccountModel>
}
User: {
model: TypeORMUserModel
schema: Schema<TypeORMUserModel>
}
Session: {
model: TypeORMSessionModel
schema: Schema<TypeORMSessionModel>
}
VerificationRequest: {
model: TypeORMVerificationRequestModel
schema: Schema<TypeORMVerificationRequestModel>
}
}
}
interface PrismaAdapter {
Adapter: (config: {
prisma: any
modelMapping?: {
User: string
Account: string
Session: string
VerificationRequest: string
}
}) => Adapter
}
declare const Adapters: Adapters
declare class TypeORMAccountModel {
compoundId: string
userId: number
providerType: string
providerId: string
providerAccountId: string
refreshToken?: string
accessToken?: string
accessTokenExpires?: Date
constructor(
userId: number,
providerId: string,
providerType: string,
providerAccountId: string,
refreshToken?: string,
accessToken?: string,
accessTokenExpires?: Date
)
}
declare class TypeORMUserModel implements User {
name?: string
email?: string
image?: string
emailVerified?: Date
constructor(
name?: string,
email?: string,
image?: string,
emailVerified?: Date
)
}
declare class TypeORMSessionModel implements Session {
userId: number
expires: Date
sessionToken: string
accessToken: string
constructor(
userId: number,
expires: Date,
sessionToken?: string,
accessToken?: string
)
}
declare class TypeORMVerificationRequestModel implements VerificationRequest {
identifier: string
token: string
expires: Date
constructor(identifier: string, token: string, expires: Date)
}
export default Adapters
export {
Adapter,
Adapters,
TypeORMAdapter,
TypeORMAccountModel,
TypeORMUserModel,
TypeORMSessionModel,
TypeORMVerificationRequestModel,
PrismaAdapter,
}

97
types/client.d.ts vendored
View File

@@ -1,97 +0,0 @@
import { FC } from "react"
import { IncomingMessage } from "http"
import { WithAdditionalParams } from "./_utils"
import { Session } from "."
import { AppProvider, DefaultProviders, Providers } from "./providers"
interface ContextProviderProps {
session: WithAdditionalParams<Session> | null | undefined
options?: SetOptionsParams
}
interface SetOptionsParams {
baseUrl?: string
basePath?: string
clientMaxAge?: number
keepAlive?: number
}
interface SignInResponse {
error: string | undefined
status: number
ok: boolean
url: string | null
}
type ContextProvider = FC<ContextProviderProps>
interface NextContext {
req?: IncomingMessage
ctx?: { req: IncomingMessage }
}
declare function useSession(): [Session | null | undefined, boolean]
declare function providers(): Promise<Record<
keyof DefaultProviders | string,
AppProvider
> | null>
declare const getProviders: typeof providers
declare function session(
context?: NextContext & {
triggerEvent?: boolean
}
): Promise<Session | null>
declare const getSession: typeof session
declare function csrfToken(context?: NextContext): Promise<string | null>
declare const getCsrfToken: typeof csrfToken
declare function signin(
provider: "credentials" | "email",
data?: Record<string, unknown> & {
callbackUrl?: string
redirect?: false
},
authorizationParams?:
| string
| string[][]
| Record<string, unknown>
| URLSearchParams
): Promise<SignInResponse>
declare function signin(
provider?: string,
data?: Record<string, unknown> & {
callbackUrl?: string
redirect?: boolean
},
authorizationParams?:
| string
| string[][]
| Record<string, unknown>
| URLSearchParams
): Promise<void>
declare const signIn: typeof signin
declare function signout(data?: {
callbackUrl?: string
redirect?: boolean
}): Promise<void>
declare const signOut: typeof signout
declare function options(options: SetOptionsParams): void
declare const setOptions: typeof options
declare const Provider: ContextProvider
export {
useSession,
session,
getSession,
providers,
getProviders,
csrfToken,
getCsrfToken,
signin,
signIn,
signout,
signOut,
options,
setOptions,
Provider,
}

169
types/index.d.ts vendored
View File

@@ -1,169 +0,0 @@
// Minimum TypeScript Version: 3.5
/// <reference types="node" />
import { ConnectionOptions } from "typeorm"
import { Adapter } from "./adapters"
import { JWTEncodeParams, JWTDecodeParams, JWTOptions, JWT } from "./jwt"
import { AppProvider, Providers } from "./providers"
import { NextApiRequest, NextApiResponse, NextApiHandler } from "./_next"
import { NonNullParams, WithAdditionalParams } from "./_utils"
export interface NextAuthOptions {
providers: Providers
database?: string | Record<string, any> | ConnectionOptions
secret?: string
session?: SessionOptions
jwt?: JWTOptions
pages?: PagesOptions
callbacks?: CallbacksOptions
debug?: boolean
adapter?: Adapter
events?: EventsOptions
useSecureCookies?: boolean
cookies?: CookiesOptions
logger?: LoggerInstance
theme?: "light" | "dark" | "auto"
}
export interface LoggerInstance {
warn: (code?: string, ...message: unknown[]) => void
error: (code?: string, ...message: unknown[]) => void
debug: (code?: string, ...message: unknown[]) => void
}
interface InternalOptions
extends Omit<
NextAuthOptions,
"providers" | "database" | "session" | "useSecureCookie"
> {
pkce: {
code_verifier?: string
code_challenge_method?: "S256"
}
provider?: string
baseUrl?: string
basePath?: string
action?:
| "providers"
| "session"
| "csrf"
| "signin"
| "signout"
| "callback"
| "verify-request"
| "error"
csrfToken?: string
}
export interface AppOptions
extends Omit<NextApiRequest, "cookies">,
NonNullParams<InternalOptions> {
providers: AppProvider[]
}
export interface CallbacksOptions {
signIn?:
| (() => true)
| ((
user: User,
account: Record<string, unknown>,
profile: Record<string, unknown>
) => Promise<never | string | boolean>)
redirect?: (url: string, baseUrl: string) => Promise<string>
session?:
| ((session: Session) => WithAdditionalParams<Session>)
| ((
session: Session,
userOrToken: User | JWT
) => Promise<WithAdditionalParams<Session>>)
jwt?:
| ((token: JWT) => WithAdditionalParams<JWT>)
| ((
token: JWT,
user: User,
account: Record<string, unknown>,
profile: Record<string, unknown>,
isNewUser: boolean
) => Promise<WithAdditionalParams<JWT>>)
}
export interface CookieOption {
name: string
options: {
httpOnly: boolean
sameSite: true | "strict" | "lax" | "none"
path?: string
secure: boolean
maxAge?: number
domain?: string
}
}
export interface CookiesOptions {
sessionToken?: CookieOption
callbackUrl?: CookieOption
csrfToken?: CookieOption
pkceCodeVerifier?: CookieOption
}
export type EventType =
| "signIn"
| "signOut"
| "createUser"
| "updateUser"
| "linkAccount"
| "session"
| "error"
export type EventCallback = (message: any) => Promise<void>
export type EventsOptions = Partial<Record<EventType, EventCallback>>
export interface PagesOptions {
signIn?: string
signOut?: string
error?: string
verifyRequest?: string
newUser?: string | null
}
export interface Session {
user: WithAdditionalParams<User>
accessToken?: string
expires: string
}
export interface SessionOptions {
jwt?: boolean
maxAge?: number
updateAge?: number
}
export interface User {
name?: string | null
email?: string | null
image?: string | null
}
export interface NextAuthRequest extends NextApiRequest {
options: InternalOptions
}
export type NextAuthResponse = NextApiResponse
declare function NextAuthHandler(
req: NextApiRequest,
res: NextApiResponse,
options?: NextAuthOptions
): ReturnType<NextApiHandler>
declare function NextAuth(
req: NextApiRequest,
res: NextApiResponse,
options?: NextAuthOptions
): ReturnType<NextApiHandler>
declare function NextAuth(
options: NextAuthOptions
): ReturnType<typeof NextAuthHandler>
export { NextAuthHandler, NextAuth }
export default NextAuth

67
types/jwt.d.ts vendored
View File

@@ -1,67 +0,0 @@
import { JWT, JWE } from "jose"
import { NextApiRequest } from "./_next"
import { WithAdditionalParams } from "./_utils"
export interface JWT extends Record<string, unknown> {
name?: string | null
email?: string | null
picture?: string | null
}
export interface JWTEncodeParams {
token?: WithAdditionalParams<JWT>
maxAge?: number
secret: string | Buffer
signingKey?: string
signingOptions?: JWT.SignOptions
encryptionKey?: string
encryptionOptions?: object
encryption?: boolean
}
export interface JWTDecodeParams {
token?: string
maxAge?: number
secret: string | Buffer
signingKey?: string
verificationKey?: string
verificationOptions?: JWT.VerifyOptions<false>
encryptionKey?: string
decryptionKey?: string
decryptionOptions?: JWE.DecryptOptions<false>
encryption?: boolean
}
export interface JWTOptions {
secret?: string
maxAge?: number
encryption?: boolean
signingKey?: string
encryptionKey?: string
encode?: (options: JWTEncodeParams) => Promise<string>
decode?: (options: JWTDecodeParams) => Promise<WithAdditionalParams<JWT>>
}
declare function encode(args?: JWTEncodeParams): Promise<string>
declare function decode(
args?: JWTDecodeParams & { token: string }
): Promise<WithAdditionalParams<JWT>>
declare function getToken(
args?: {
req: NextApiRequest
secureCookie?: boolean
cookieName?: string
raw?: string
} & JWTDecodeParams
): Promise<WithAdditionalParams<JWT>>
declare function getToken(args?: {
req: NextApiRequest
secureCookie?: boolean
cookieName?: string
raw: true
}): Promise<string>
export { encode, decode, getToken }

435
types/providers.d.ts vendored
View File

@@ -1,435 +0,0 @@
import { User } from "."
import { JWT } from "./jwt"
import { NonNullParams, NullableParams, WithAdditionalParams } from "./_utils"
export interface Provider<
T extends string | undefined = undefined,
U = T extends string ? "oauth" : string
> {
id: T
name: string
type: U extends string ? U : "oauth" | "email" | "credentials"
version: string
scope: string
params: { grant_type: string }
accessTokenUrl: string
requestTokenUrl: string
authorizationUrl: string
profileUrl: string
profile: (
profile: Record<string, any>,
tokens: any
) => (User & { id: string }) | Promise<User & { id: string }>
clientId: string
clientSecret: string | Record<string, unknown>
idToken?: boolean
}
export interface AppProvider extends Pick<Provider, "id" | "name" | "type"> {
signinUrl: string
callbackUrl: string
}
export interface DefaultProviders {
Apple: Apple
Attlassian: Atlassian
Auth0: Auth0
AzureADB2C: AzureADB2C
Basecamp: Basecamp
BattleNet: BattleNet
Box: Box
Bungie: Bungie
Cognito: Cognito
Credentials: Credentials
Discord: Discord
Email: Email
EVEOnline: EVEOnline
Facebook: Facebook
FACEIT: FACEIT
Foursquare: Foursquare
FusionAuth: FusionAuth
GitHub: GitHub
GitLab: GitLab
Google: Google
IdentityServer4: IdentityServer4
Instagram: Instagram
Kakao: Kakao
LINE: LINE
LinkedIn: LinkedIn
MailRu: MailRu
Medium: Medium
Netlify: Netlify
Okta: Okta
Osso: Osso
Reddit: Reddit
Salesforce: Salesforce
Slack: Slack
Spotify: Spotify
Strava: Strava
Twitch: Twitch
Twitter: Twitter
VK: VK
Yandex: Yandex
Zoho: Zoho
}
export type Providers = Array<
Provider | ReturnType<DefaultProviders[keyof DefaultProviders]>
>
declare const Providers: DefaultProviders
export default Providers
/**
* Email
*/
type Email = (
options: ProviderEmailOptions
) => NonNullParams<ProviderEmailOptions> & { id: "email"; type: "email" }
interface VerificationRequestParams extends Provider {
identifier: string
url: string
baseUrl: string
token: string
provider: ProviderEmailOptions
}
interface ProviderEmailOptions {
name?: string
server?: string | ProviderEmailServer
from?: string
maxAge?: number
sendVerificationRequest?: (
options: VerificationRequestParams
) => Promise<void>
}
interface ProviderEmailServer {
host: string
port: number
auth: {
user: string
pass: string
}
}
/**
* Credentials
*/
type Credentials = (
options: ProviderCredentialsOptions
) => NonNullParams<ProviderCredentialsOptions> & {
id: "credentials"
type: "credentials"
}
interface ProviderCredentialsOptions {
id?: string
name: string
credentials: CredentialInput
authorize: (credentials: Record<string, string>) => Promise<User | null>
}
interface CredentialInput {
[key: string]: {
label?: string
type?: string
value?: string
placeholder?: string
}
}
type OptionsBase = {
[K in keyof Omit<Provider, "id">]?: Provider[K]
}
/**
* Provider options
* @link https://next-auth.js.org/configuration/providers#oauth-provider-options
*/
interface ProviderCommonOptions extends OptionsBase {
authorizationParams?: Record<string, string>
clientId: string
clientSecret: string
headers?: Record<string, any>
idToken?: boolean
name?: string
protection?: "pkce" | "state" | "both" | "none"
state?: boolean
}
/**
* Apple
*/
type Apple = (
options: ProviderAppleOptions
) => Provider<"apple"> & { protection: "none" }
interface ProviderAppleOptions
extends Omit<ProviderCommonOptions, "clientSecret"> {
name?: string
clientId: string
clientSecret: Record<"appleId" | "teamId" | "privateKey" | "keyId", string>
}
interface ProviderAppleSecret {
appleId: string
teamId: string
privateKey: string
keyId: string
}
/**
* Twitter
*/
type Twitter = (options: ProviderCommonOptions) => Provider<"twitter">
/**
* Facebook
*/
type Facebook = (options: ProviderCommonOptions) => Provider<"facebook">
/**
* GitHub
*/
type GitHub = (options: ProviderGitHubOptions) => Provider<"github">
interface ProviderGitHubOptions extends Omit<ProviderCommonOptions, "scope"> {
scope?: string
}
/**
* GitLab
*/
type GitLab = (options: ProviderCommonOptions) => Provider<"gitlab">
/**
* Slack
*/
type Slack = (options: ProviderCommonOptions) => Provider<"slack">
/**
* Google
*/
type Google = (options: ProviderGoogleOptions) => Provider<"google">
interface ProviderGoogleOptions extends ProviderCommonOptions {
authorizationUrl?: string
}
/**
* Auth0
*/
type Auth0 = (
options: ProviderAuth0Options
) => Provider<"auth0"> & { domain: string }
interface ProviderAuth0Options extends Omit<ProviderCommonOptions, "profile"> {
domain: string
profile?: (profile: Auth0Profile) => User & { id: string }
}
interface Auth0Profile {
sub: string
nickname: string
email: string
picture: string
}
/**
* IS4
*/
type IdentityServer4 = (
options: ProviderIS4Options
) => Provider<"identity-server4" | string> & { domain: string }
interface ProviderIS4Options extends Omit<ProviderCommonOptions, "id"> {
id: string
scope: string
domain: string
}
/**
* Discord
*/
type Discord = (options: ProviderCommonOptions) => Provider<"discord">
/**
* Twitch
*/
type Twitch = (options: ProviderCommonOptions) => Provider<"twitch">
/**
* Okta
*/
type Okta = (
options: ProviderOktaOptions
) => Provider<"okta"> & { domain: string }
interface ProviderOktaOptions extends ProviderCommonOptions {
domain: string
}
/**
* Battle.net
*/
type BattleNet = (
options: ProviderBattleNetOptions
) => Provider<"battlenet"> & { region: string }
interface ProviderBattleNetOptions extends ProviderCommonOptions {
region: string
}
/**
* Box
*/
type Box = (options: ProviderCommonOptions) => Provider<"box">
/**
* Cognito
*/
type Cognito = (
options: ProviderCognitoOptions
) => Provider<"cognito"> & { domain: string }
interface ProviderCognitoOptions extends ProviderCommonOptions {
domain: string
}
/**
* Yandex
*/
type Yandex = (options: ProviderCommonOptions) => Provider<"yandex">
/**
* LinkedIn
*/
type LinkedIn = (options: ProviderLinkedInOptions) => Provider<"linkedin">
interface ProviderLinkedInOptions extends ProviderCommonOptions {
scope?: string
}
/**
* Spotify
*/
type Spotify = (options: ProviderSpotifyOptions) => Provider<"spotify">
interface ProviderSpotifyOptions extends ProviderCommonOptions {
scope?: string
}
/**
* Basecamp
*/
type Basecamp = (options: ProviderCommonOptions) => Provider<"basecamp">
/**
* Reddit
*/
type Reddit = (options: ProviderCommonOptions) => Provider<"reddit">
/**
* Atlassian
*/
type Atlassian = (options: ProviderCommonOptions) => Provider<"atlassian">
/**
* AzureADB2C
*/
type AzureADB2C = (
options: ProviderAzureADB2COptions
) => Provider<"azure-ad-b2c">
interface ProviderAzureADB2COptions extends ProviderCommonOptions {
tenantId?: string
}
/**
* Bungie
*/
type Bungie = (options: ProviderCommonOptions) => Provider<"bungie">
/**
* EVEOnline
*/
type EVEOnline = (options: ProviderCommonOptions) => Provider<"eveonline">
/**
* FACEIT
*/
type FACEIT = (options: ProviderCommonOptions) => Provider<"faceit">
/**
* Foursquare
*/
type Foursquare = (options: ProviderCommonOptions) => Provider<"foursquare">
/**
* FusionAuth
*/
type FusionAuth = (options: ProviderFusionAuthOptions) => Provider<"fusionauth">
interface ProviderFusionAuthOptions extends ProviderCommonOptions {
tenantId?: string
domain?: string
}
/**
* Instagram
*/
type Instagram = (options: ProviderCommonOptions) => Provider<"instagram">
/**
* Kakao
*/
type Kakao = (options: ProviderCommonOptions) => Provider<"kakao">
/**
* LINE
*/
type LINE = (options: ProviderCommonOptions) => Provider<"line">
/**
* MailRu
*/
type MailRu = (options: ProviderCommonOptions) => Provider<"mailru">
/**
* Medium
*/
type Medium = (options: ProviderCommonOptions) => Provider<"medium">
/**
* Netlify
*/
type Netlify = (options: ProviderCommonOptions) => Provider<"netlify">
/**
* Osso
*/
type Osso = (options: ProviderCommonOptions) => Provider<"osso">
/**
* Salesforce
*/
type Salesforce = (options: ProviderCommonOptions) => Provider<"salesforce">
/**
* Strava
*/
type Strava = (options: ProviderCommonOptions) => Provider<"strava">
/**
* VK
*/
type VK = (options: ProviderCommonOptions) => Provider<"vk">
/**
* Zoho
*/
type Zoho = (options: ProviderCommonOptions) => Provider<"zoho">

View File

@@ -1,26 +0,0 @@
import Adapters, { TypeORMAdapter } from "next-auth/adapters"
// ExpectType TypeORMAdapter["Adapter"]
Adapters.Default({
type: "sqlite",
database: ":memory:",
synchronize: true,
})
// ExpectType TypeORMAdapter
Adapters.TypeORM.Adapter({
type: "sqlite",
database: ":memory:",
synchronize: true,
})
// ExpectType PrismaAdapter
Adapters.Prisma.Adapter({
prisma: {},
modelMapping: {
User: "foo",
Account: "bar",
Session: "session",
VerificationRequest: "foo",
},
})

View File

@@ -1,83 +0,0 @@
import * as client from "next-auth/client"
import { nextReq } from "./test-helpers"
const clientSession = {
user: {
name: "Bruce",
email: "bruce@lee.com",
image: "path/to/img",
},
accessToken: "123z",
expires: "1234",
}
// $ExpectType [Session | null | undefined, boolean]
client.useSession()
// $ExpectType Promise<Session | null>
client.getSession({ req: nextReq })
// $ExpectType Promise<Session | null>
client.session({ req: nextReq })
// $ExpectType Promise<Record<string, AppProvider> | null>
client.getProviders()
// $ExpectType Promise<Record<string, AppProvider> | null>
client.providers()
// $ExpectType Promise<string | null>
client.getCsrfToken({ req: nextReq })
// $ExpectType Promise<string | null>
client.csrfToken({ req: nextReq })
// $ExpectType Promise<void>
client.signin("github", { data: "foo", redirect: false }, { login: "username" })
// $ExpectType Promise<SignInResponse>
client.signin("credentials", { data: "foo", redirect: false })
// $ExpectType Promise<SignInResponse>
client.signin("email", { data: "foo", redirect: false })
// $ExpectType Promise<void>
client.signin("email", { data: "foo", redirect: true })
// $ExpectType Promise<void>
client.signout()
// $ExpectType Promise<void>
client.signout({ callbackUrl: "https://foo.com/callback", redirect: true })
// $ExpectType ReactElement<any, any> | null
client.Provider({
session: clientSession,
options: {
baseUrl: "https://foo.com",
basePath: "/",
clientMaxAge: 1234,
},
})
// $ExpectType ReactElement<any, any> | null
client.Provider({
session: clientSession,
})
// $ExpectType ReactElement<any, any> | null
client.Provider({
session: undefined,
options: {},
})
// $ExpectType ReactElement<any, any> | null
client.Provider({
session: null,
options: {
baseUrl: "https://foo.com",
basePath: "/",
clientMaxAge: 1234,
keepAlive: 4321,
},
})

View File

@@ -1,26 +0,0 @@
import * as JWTType from "next-auth/jwt"
import { nextReq } from "./test-helpers"
// $ExpectType Promise<string>
JWTType.encode({
token: { key: "value" },
secret: "secret",
})
// $ExpectType Promise<WithAdditionalParams<JWT>>
JWTType.decode({
token: "token",
secret: "secret",
})
// $ExpectType Promise<string>
JWTType.getToken({
req: nextReq,
raw: true,
})
// $ExpectType Promise<WithAdditionalParams<JWT>>
JWTType.getToken({
req: nextReq,
secret: "secret",
})

View File

@@ -1,259 +0,0 @@
import Providers from "next-auth/providers"
// $ExpectType NonNullParams<ProviderEmailOptions> & { id: "email"; type: "email"; }
Providers.Email({
server: "path/to/server",
from: "path/from",
})
// $ExpectType NonNullParams<ProviderEmailOptions> & { id: "email"; type: "email"; }
Providers.Email({
server: {
host: "host",
port: 123,
auth: {
user: "foo",
pass: "123",
},
},
from: "path/from",
})
// $ExpectType NonNullParams<ProviderCredentialsOptions> & { id: "credentials"; type: "credentials"; }
Providers.Credentials({
id: "login",
name: "account",
credentials: {
user: {
label: "Password",
type: "password",
},
password: {
label: "Password",
type: "password",
},
},
authorize: async (credentials) => {
const user = {
/* fetched user */
}
return user
},
})
// $ExpectType Provider<"apple", "oauth"> & { protection: "none"; }
Providers.Apple({
clientId: "foo123",
clientSecret: {
appleId: "foo@icloud.com",
teamId: "foo",
privateKey: "123xyz",
keyId: "1234",
},
})
// $ExpectType Provider<"twitter", "oauth">
Providers.Twitter({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"facebook", "oauth">
Providers.Facebook({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"github", "oauth">
Providers.GitHub({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"github", "oauth">
Providers.GitHub({
clientId: "foo123",
clientSecret: "bar123",
scope: "change:thing read:that",
})
// $ExpectType Provider<"gitlab", "oauth">
Providers.GitLab({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"slack", "oauth">
Providers.Slack({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"google", "oauth">
Providers.Google({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"google", "oauth">
Providers.Google({
clientId: "foo123",
clientSecret: "bar123",
authorizationUrl: "https://foo.google.com",
})
// $ExpectType Provider<"auth0", "oauth"> & { domain: string; }
Providers.Auth0({
clientId: "foo123",
clientSecret: "bar123",
domain: "https://foo.auth0.com",
})
// $ExpectType Provider<"auth0", "oauth"> & { domain: string; }
Providers.Auth0({
clientId: "foo123",
clientSecret: "bar123",
domain: "https://foo.auth0.com",
profile: () => ({
id: "foo123",
name: "foo",
email: "foo@bar.io",
image: "https://foo.auth0.com/image/1.png",
}),
})
// $ExpectType Provider<string, "oauth"> & { domain: string; }
Providers.IdentityServer4({
id: "identity-server4",
name: "IdentityServer4",
scope: "change:thing read:that",
domain: "https://foo.is4.com",
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"discord", "oauth">
Providers.Discord({
clientId: "foo123",
clientSecret: "bar123",
scope: "identify",
})
// $ExpectType Provider<"twitch", "oauth">
Providers.Twitch({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"okta", "oauth"> & { domain: string; }
Providers.Okta({
clientId: "foo123",
clientSecret: "bar123",
domain: "https://foo.auth0.com",
})
// $ExpectType Provider<"battlenet", "oauth"> & { region: string; }
Providers.BattleNet({
clientId: "foo123",
clientSecret: "bar123",
region: "europe",
})
// $ExpectType Provider<"box", "oauth">
Providers.Box({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"cognito", "oauth"> & { domain: string; }
Providers.Cognito({
clientId: "foo123",
clientSecret: "bar123",
domain: "https://foo.auth0.com",
})
// $ExpectType Provider<"yandex", "oauth">
Providers.Yandex({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"linkedin", "oauth">
Providers.LinkedIn({
clientId: "foo123",
clientSecret: "bar123",
scope: "r_emailaddress r_liteprofile",
})
// $ExpectType Provider<"spotify", "oauth">
Providers.Spotify({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"spotify", "oauth">
Providers.Spotify({
clientId: "foo123",
clientSecret: "bar123",
scope: "user-read-email",
})
// $ExpectType Provider<"basecamp", "oauth">
Providers.Basecamp({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"reddit", "oauth">
Providers.Reddit({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"azure-ad-b2c", "oauth">
Providers.AzureADB2C({
clientId: "foo123",
clientSecret: "bar123",
scope: "offline_access User.Read",
tenantId: "tenantId",
idToken: true,
})
// $ExpectType Provider<"fusionauth", "oauth">
Providers.FusionAuth({
name: "FusionAuth",
domain: "domain",
clientId: "clientId",
clientSecret: "clientSecret",
tenantId: "tenantId",
})
// $ExpectType Provider<"faceit", "oauth">
Providers.FACEIT({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"instagram", "oauth">
Providers.Instagram({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"kakao", "oauth">
Providers.Kakao({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"osso", "oauth">
Providers.Osso({
clientId: "foo123",
clientSecret: "bar123",
})
// $ExpectType Provider<"zoho", "oauth">
Providers.Zoho({
clientId: "foo123",
clientSecret: "bar123",
})

View File

@@ -1,255 +0,0 @@
import Providers, { AppProvider, Provider } from "next-auth/providers"
import Adapters, {
Adapter,
EmailAppProvider,
Profile,
Session,
VerificationRequest,
} from "next-auth/adapters"
import NextAuth, * as NextAuthTypes from "next-auth"
import { IncomingMessage, ServerResponse } from "http"
import * as JWTType from "next-auth/jwt"
import { Socket } from "net"
import { NextApiRequest, NextApiResponse } from "next"
const req: NextApiRequest = Object.assign(new IncomingMessage(new Socket()), {
query: {},
cookies: {},
body: {},
env: {},
})
const res: NextApiResponse = Object.assign(new ServerResponse(req), {
send: (body: string) => undefined,
json: (body: string) => undefined,
status: (code: number) => res,
redirect: (statusOrUrl: number | string, url?: string) => res as any,
setPreviewData: (data: object | string) => res,
clearPreviewData: () => res,
})
const pageOptions = {
signin: "path/to/signin",
signout: "path/to/signout",
error: "path/to/error",
verifyRequest: "path/to/verify",
newUsers: "path/to/signup",
}
const simpleConfig = {
site: "https://foo.com",
providers: [
Providers.GitHub({
clientId: "123",
clientSecret: "123",
scope:
"user public_repo repo repo_deployment repo:status read:repo_hook read:org read:public_key read:gpg_key",
}),
],
}
const exampleUser: NextAuthTypes.User = {
name: "",
image: "",
email: "",
}
const exampleSession: Session = {
userId: "",
accessToken: "",
sessionToken: "",
expires: new Date(),
}
const exampleVerificatoinRequest: VerificationRequest = {
identifier: "",
token: "",
expires: new Date(),
}
const adapter: Adapter<
NextAuthTypes.User,
Profile,
Session,
VerificationRequest
> = {
async getAdapter(appOptions: NextAuthTypes.AppOptions) {
return {
createUser: async (profile: Profile) => exampleUser,
getUser: async (id: string) => exampleUser,
getUserByEmail: async (email: string) => exampleUser,
getUserByProviderAccountId: async (
providerId: string,
providerAccountId: string
) => exampleUser,
updateUser: async (user: NextAuthTypes.User) => exampleUser,
linkAccount: async (
userId: string,
providerId: string,
providerType: string,
providerAccountId: string,
refreshToken: string,
accessToken: string,
accessTokenExpires: number
) => undefined,
createSession: async (user: NextAuthTypes.User) => exampleSession,
getSession: async (sessionToken: string) => exampleSession,
updateSession: async (session: Session, force?: boolean) =>
exampleSession,
deleteSession: async (sessionToken: string) => undefined,
createVerificationRequest: async (
email: string,
url: string,
token: string,
secret: string,
provider: EmailAppProvider,
options: NextAuthTypes.AppOptions
) => exampleVerificatoinRequest,
getVerificationRequest: async (
email: string,
verificationToken: string,
secret: string,
provider: AppProvider
) => exampleVerificatoinRequest,
deleteVerificationRequest: async (
email: string,
verificationToken: string,
secret: string,
provider: AppProvider
) => undefined,
}
},
}
const allConfig = {
providers: [
Providers.Twitter({
clientId: "123",
clientSecret: "123",
}),
],
database: "path/to/db",
debug: true,
secret: "my secret",
session: {
jwt: true,
maxAge: 365,
updateAge: 60,
},
jwt: {
secret: "secret-thing",
maxAge: 365,
encryption: true,
signingKey: "some-key",
encryptionKey: "some-key",
encode: async () => "foo",
decode: async () => ({}),
},
pages: pageOptions,
callbacks: {
async signIn(
user: NextAuthTypes.User,
account: Record<string, unknown>,
profile: Record<string, unknown>
) {
return true
},
async redirect(url: string, baseUrl: string) {
return "path/to/foo"
},
async session(
session: NextAuthTypes.Session,
userOrToken: NextAuthTypes.User
) {
return { ...session }
},
async jwt(
token: JWTType.JWT,
user: NextAuthTypes.User,
account: Record<string, unknown>,
profile: Record<string, unknown>,
isNewUser: boolean
) {
return token
},
},
events: {
async signIn(message: string) {
return undefined
},
async signOut(message: string) {
return undefined
},
async createUser(message: string) {
return undefined
},
async linkAccount(message: string) {
return undefined
},
async session(message: string) {
return undefined
},
async error(message: string) {
return undefined
},
},
adapter,
useSecureCookies: true,
cookies: {
sessionToken: {
name: "__Secure-next-auth.session-token",
options: {
httpOnly: true,
sameSite: true as true,
path: "/",
secure: true,
domain: "foo.com",
},
},
},
}
const customProvider: Provider<"google"> = {
id: "google",
name: "Google",
type: "oauth",
version: "2.0",
scope:
"https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
params: { grant_type: "authorization_code" },
accessTokenUrl: "https://accounts.google.com/o/oauth2/token",
requestTokenUrl: "https://accounts.google.com/o/oauth2/auth",
authorizationUrl:
"https://accounts.google.com/o/oauth2/auth?response_type=code",
profileUrl: "https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
async profile(profile, tokens) {
return {
id: profile.id,
name: profile.name,
email: profile.email,
image: profile.picture,
}
},
clientId: "",
clientSecret: "",
}
const customProviderConfig = {
site: "https://foo.com",
providers: [customProvider],
}
// $ExpectType void | Promise<void>
NextAuth(simpleConfig)
// $ExpectType void | Promise<void>
NextAuth(allConfig)
// $ExpectType void | Promise<void>
NextAuth(customProviderConfig)
// $ExpectType void | Promise<void>
NextAuth(req, res, simpleConfig)
// $ExpectType void | Promise<void>
NextAuth(req, res, allConfig)

View File

@@ -1,13 +0,0 @@
import { IncomingMessage, ServerResponse } from "http"
import { Socket } from "net"
import { NextApiRequest } from "next"
export const nextReq: NextApiRequest = Object.assign(
new IncomingMessage(new Socket()),
{
query: {},
cookies: {},
body: {},
env: {},
}
)

View File

@@ -1,23 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es6", "dom"],
"jsx": "react",
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"esModuleInterop": true,
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"next-auth": ["."],
"next-auth/providers": ["./providers"],
"next-auth/adapters": ["./adapters"],
"next-auth/client": ["./client"],
"next-auth/jwt": ["./jwt"],
"next": ["./_next"]
}
}
}

View File

@@ -1,6 +0,0 @@
{
"extends": "dtslint/dtslint.json",
"rules": {
"semicolon": false
}
}

View File

@@ -79,7 +79,7 @@ When using NextAuth.js without a database, the user object it will always be a p
:::
:::tip
If you only want to allow users who already have accounts in the database to sign in, you can check for the existance of a `user.id` property and reject any sign in attempts from accounts that do not have one.
If you only want to allow users who already have accounts in the database to sign in, you can check for the existence of a `user.id` property and reject any sign in attempts from accounts that do not have one.
If you are using NextAuth.js without database and want to control who can sign in, you can check their email address or profile against a hard coded list in the `signIn()` callback.
:::

View File

@@ -121,11 +121,29 @@ By default JSON Web Tokens are signed (JWS) but not encrypted (JWE), as JWT encr
jwt: {
// A secret to use for key generation - you should set this explicitly
// Defaults to NextAuth.js secret if not explicitly specified.
// This is used to generate the actual signingKey and produces a warning
// message if not defined explicitly.
// secret: 'INp8IvdIyeMcoGAgFGoA61DdBglwwSqnXJZkgz8PSnw',
// You can generate a signing key using `jose newkey -s 512 -t oct -a HS512`
// This gives you direct knowledge of the key used to sign the token so you can use it
// to authenticate indirectly (eg. to a database driver)
// signingKey: {"kty":"oct","kid":"Dl893BEV-iVE-x9EC52TDmlJUgGm9oZ99_ZL025Hc5Q","alg":"HS512","k":"K7QqRmJOKRK2qcCKV_pi9PSBv3XP0fpTu30TP8xn4w01xR3ZMZM38yL2DnTVPVw6e4yhdh0jtoah-i4c_pZagA"},
// If you chose something other than the default algorithm for the signingKey (HS512)
// you also need to configure the algorithm
// verificationOptions: {
// algorithms: ['HS256']
// },
// Set to true to use encryption. Defaults to false (signing only).
// encryption: true,
// encryptionKey: "",
// decryptionKey = encryptionKey,
// decryptionOptions = {
// algorithms: ['A256GCM']
// },
// You can define your own encode/decode functions for signing and encryption
// if you want to override the default behaviour.
// async encode({ secret, token, maxAge }) {},

View File

@@ -141,7 +141,7 @@ You can look at the existing built-in providers for inspiration.
| profile | An callback returning an object with the user's info | `object` | No |
| idToken | Set to `true` for services that use ID Tokens (e.g. OpenID) | `boolean` | No |
| headers | Any headers that should be sent to the OAuth provider | `object` | No |
| protection | Additional security for OAuth login flows (defaults to `state`) | `pkce`, `state`, `none` | No |
| protection | Additional security for OAuth login flows (defaults to `state`) |`[pkce]`,`[state]`,`[pkce,state]`| No |
| state | Same as `protection: "state"`. Being deprecated, use protection. | `boolean` | No |
## Sign in with Email

View File

@@ -185,7 +185,7 @@ Once you have saved your schema, use the Prisma CLI to generate the Prisma Clien
npx prisma generate
```
To configure you database to use the new schema (i.e. create tables and columns) use the `primsa migrate` command:
To configure you database to use the new schema (i.e. create tables and columns) use the `prisma migrate` command:
```
npx prisma migrate dev --preview-feature