mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
8 Commits
@auth/soli
...
v3.14.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1e30507c2 | ||
|
|
2c4fce3699 | ||
|
|
8fa71512d1 | ||
|
|
d420eeff9d | ||
|
|
0d863d38bc | ||
|
|
6f9f42a85b | ||
|
|
2160be2a8a | ||
|
|
55eb066793 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -6,10 +6,12 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- beta
|
||||
- next
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- beta
|
||||
- next
|
||||
|
||||
jobs:
|
||||
|
||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -13,7 +13,7 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, next ]
|
||||
branches: [ main, beta, next ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
|
||||
11
.github/workflows/integration.yml
vendored
11
.github/workflows/integration.yml
vendored
@@ -2,9 +2,10 @@ name: Integration Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- next
|
||||
branches:
|
||||
- main
|
||||
- beta
|
||||
- next
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
@@ -17,7 +18,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
|
||||
@@ -45,7 +46,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}}
|
||||
|
||||
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -3,6 +3,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'beta'
|
||||
- 'next'
|
||||
- '3.x'
|
||||
pull_request:
|
||||
|
||||
25
.github/workflows/types.yml
vendored
Normal file
25
.github/workflows/types.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
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
|
||||
3
.npmignore
Normal file
3
.npmignore
Normal file
@@ -0,0 +1,3 @@
|
||||
./types/tests/
|
||||
./types/tests/tsconfig.json
|
||||
./types/tests/tslint.json
|
||||
3
.prettierrc
Normal file
3
.prettierrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"semi": false
|
||||
}
|
||||
23
config/build-types.js
Normal file
23
config/build-types.js
Normal file
@@ -0,0 +1,23 @@
|
||||
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`)
|
||||
}
|
||||
)
|
||||
})
|
||||
26891
package-lock.json
generated
26891
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@@ -7,9 +7,10 @@
|
||||
"author": "Iain Collins <me@iaincollins.com>",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "npm run build:js && npm run build:css",
|
||||
"build": "npm run build:js && npm run build:css && npm run build:types",
|
||||
"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",
|
||||
@@ -17,13 +18,14 @@
|
||||
"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",
|
||||
"test": "npm run test:app:rebuild && npm run test:integration && npm run test:app:stop && npm run test:types",
|
||||
"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",
|
||||
@@ -35,10 +37,17 @@
|
||||
"files": [
|
||||
"dist",
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"providers.js",
|
||||
"providers.d.ts",
|
||||
"adapters.js",
|
||||
"adapters.d.ts",
|
||||
"client.js",
|
||||
"jwt.js"
|
||||
"client.d.ts",
|
||||
"jwt.js",
|
||||
"jwt.d.ts",
|
||||
"_next.d.ts",
|
||||
"_utils.d.ts"
|
||||
],
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@@ -57,7 +66,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.13.1 || ^17",
|
||||
"react-dom": "^16.13.1 || ^17"
|
||||
"react-dom": "16.13.1 || ^17"
|
||||
},
|
||||
"peerOptionalDependencies": {
|
||||
"mongodb": "^3.5.9",
|
||||
@@ -81,6 +90,7 @@
|
||||
"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",
|
||||
@@ -90,6 +100,7 @@
|
||||
"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",
|
||||
@@ -103,7 +114,8 @@
|
||||
"project": "./tsconfig.json",
|
||||
"ignore": [
|
||||
"test/",
|
||||
"next-env.d.ts"
|
||||
"next-env.d.ts",
|
||||
"types/"
|
||||
],
|
||||
"globals": [
|
||||
"localStorage",
|
||||
|
||||
@@ -2,6 +2,7 @@ module.exports = {
|
||||
branches: [
|
||||
'+([0-9])?(.{+([0-9]),x}).x',
|
||||
'main',
|
||||
{ name: 'beta', prerelease: true },
|
||||
{ name: 'next', prerelease: true }
|
||||
]
|
||||
}
|
||||
|
||||
40
types/_next.d.ts
vendored
Normal file
40
types/_next.d.ts
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
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>
|
||||
14
types/_utils.d.ts
vendored
Normal file
14
types/_utils.d.ts
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
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>
|
||||
|
||||
export type Awaitable<T> = T | PromiseLike<T>
|
||||
242
types/adapters.d.ts
vendored
Normal file
242
types/adapters.d.ts
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
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
Normal file
97
types/client.d.ts
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
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,
|
||||
}
|
||||
173
types/index.d.ts
vendored
Normal file
173
types/index.d.ts
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
// Minimum TypeScript Version: 3.5
|
||||
|
||||
/// <reference types="node" />
|
||||
|
||||
import { ConnectionOptions } from "typeorm"
|
||||
import { Adapter } from "./adapters"
|
||||
import { JWTOptions, JWT } from "./jwt"
|
||||
import { AppProvider, Providers } from "./providers"
|
||||
import { NextApiRequest, NextApiResponse, NextApiHandler } from "./_next"
|
||||
import { Awaitable, 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 Account extends Record<string, unknown> {
|
||||
accessToken: string
|
||||
idToken?: string
|
||||
refreshToken?: string
|
||||
access_token: string
|
||||
expires_in?: number | null
|
||||
refresh_token?: string
|
||||
id_token?: string
|
||||
id: string
|
||||
provider: string
|
||||
type: string
|
||||
}
|
||||
export interface Profile extends Record<string, unknown> {}
|
||||
|
||||
export interface CallbacksOptions<
|
||||
P extends Record<string, unknown> = Profile,
|
||||
A extends Record<string, unknown> = Account
|
||||
> {
|
||||
signIn?(user: User, account: A, profile: P): Awaitable<string | boolean>
|
||||
redirect?(url: string, baseUrl: string): Awaitable<string>
|
||||
session?(session: Session, userOrToken: JWT | User): Awaitable<Session>
|
||||
jwt?(
|
||||
token: JWT,
|
||||
user?: User,
|
||||
account?: A,
|
||||
profile?: P,
|
||||
isNewUser?: boolean
|
||||
): Awaitable<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
Normal file
67
types/jwt.d.ts
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
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
Normal file
435
types/providers.d.ts
vendored
Normal file
@@ -0,0 +1,435 @@
|
||||
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">
|
||||
26
types/tests/adapters.test.ts
Normal file
26
types/tests/adapters.test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
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",
|
||||
},
|
||||
})
|
||||
83
types/tests/client.test.ts
Normal file
83
types/tests/client.test.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
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,
|
||||
},
|
||||
})
|
||||
26
types/tests/jwt.test.ts
Normal file
26
types/tests/jwt.test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
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",
|
||||
})
|
||||
259
types/tests/providers.test.ts
Normal file
259
types/tests/providers.test.ts
Normal file
@@ -0,0 +1,259 @@
|
||||
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",
|
||||
})
|
||||
255
types/tests/server.test.ts
Normal file
255
types/tests/server.test.ts
Normal file
@@ -0,0 +1,255 @@
|
||||
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)
|
||||
13
types/tests/test-helpers.ts
Normal file
13
types/tests/test-helpers.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
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: {},
|
||||
}
|
||||
)
|
||||
23
types/tsconfig.json
Normal file
23
types/tsconfig.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
6
types/tslint.json
Normal file
6
types/tslint.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "dtslint/dtslint.json",
|
||||
"rules": {
|
||||
"semicolon": false
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,77 @@
|
||||
---
|
||||
id: typescript
|
||||
title: TypeScript Support
|
||||
title: TypeScript
|
||||
---
|
||||
|
||||
Currently, NextAuth.js relies on the community to provide TypeScript types. You can download it from [DefinitelyTyped](https://www.npmjs.com/package/@types/next-auth).
|
||||
NextAuth.js comes with its own types, so you can safely use it in your TypeScript projects. Even if you don't use TypeScript, IDEs like VSCode will pick this up, to provide you with a better developer experience. While you are typing, you will get suggestions of what certain objects are, and sometimes also links to documentation, and examples.
|
||||
|
||||
Add it to your project with:
|
||||
:::note
|
||||
The types at [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) under the name of `@types/next-auth` are now deprecated, and not maintained anymore.
|
||||
:::
|
||||
|
||||
```sh
|
||||
npm i -D @types/next-auth
|
||||
***
|
||||
## Module Augmentaion
|
||||
|
||||
`next-auth` comes with certain types/interfaces, that are shared across submodules. Good examples are `Session` and `JWT`. Ideally, you should only need to create these types at a single place, and TS should pick them up in every location where they are referenced. Luckily, this is exactly what Module Agumentation can do for us. Define your shared interfaces in a single location, and get type-safety across your application, when you use `next-auth` (or one of its submodules).
|
||||
|
||||
1. Let's look at `Session`:
|
||||
|
||||
```ts title="pages/api/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
export default NextAuth({
|
||||
callbacks: {
|
||||
session(session, token) {
|
||||
return session // The type here should match the one returned in `useSession()`
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
or
|
||||
```ts title="pages/index.ts"
|
||||
import { useSession } from "next-auth/client"
|
||||
|
||||
```sh
|
||||
yarn add -D @types/next-auth
|
||||
export default function IndexPage() {
|
||||
// `session` should match `callbacks.session()` in `NextAuth()`
|
||||
const [session] = useSession()
|
||||
|
||||
return (
|
||||
// Your component
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
You can find an initial Pull Request at [next-auth#516](https://github.com/nextauthjs/next-auth/pull/516) adding TypeScript. At the time of this writing, it looks like we would like to go from a complete migration to a more relaxed, incremental rewrite.
|
||||
To extend/augment this type, create a `types/next-auth.d.ts` file in your project:
|
||||
|
||||
Feel free to open a Pull Request, if you would like to contribute!
|
||||
```ts title="types/next-auth.d.ts"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
declare module "next-auth" {
|
||||
interface Session {
|
||||
user: {
|
||||
/** The user's postal address. */
|
||||
address: string
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Make sure that the `types` folder is added to [`typeRoots`](https://www.typescriptlang.org/tsconfig/#typeRoots) in your project's `tsconfig.json` file.
|
||||
|
||||
2. Check out `JWT` also:
|
||||
|
||||
```ts title="types/next-auth.d.ts"
|
||||
declare module "next-auth/jwt" {
|
||||
interface JWT {
|
||||
/** OpenID ID Token */
|
||||
idToken?: string
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that this time we declared `JWT` inside `next-auth/jwt`, as this is its default location.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions of any kind are always welcome, especially for TypeScript. Please keep in mind that we are a small team working on this project in our free time. We will try our best to give support, but if you think you have a solution for a problem, please open a PR!
|
||||
|
||||
Reference in New Issue
Block a user