@auth/core
Version:
Authentication for the Web.
567 lines (542 loc) • 19.6 kB
text/typescript
/**
*
* This module contains public types and interfaces of the core package.
*
* ## Installation
*
* ```bash npm2yarn2pnpm
* npm install @auth/core
* ```
*
* You can then import this submodule from `@auth/core/type`.
*
* ## Usage
*
* Even if you don't use TypeScript, IDEs like VSCode will pick up types to provide you with a better developer experience.
* While you are typing, you will get suggestions about what certain objects/functions look like,
* and sometimes links to documentation, examples, and other valuable resources.
*
* Generally, you will not need to import types from this module.
* Mostly when using the `Auth` function and optionally the `AuthConfig` interface,
* everything inside there will already be typed.
*
* :::tip
* Inside the `Auth` function, you won't need to use a single type from this module.
*
* @example
* ```ts title=index.ts
* import { Auth } from "@auth/core"
*
* const request = new Request("https://example.com")
* const response = await Auth(request, {
* callbacks: {
* jwt(): JWT { // <-- This is unnecessary!
* return { foo: "bar" }
* },
* session(
* { session, token }: { session: Session; token: JWT } // <-- This is unnecessary!
* ) {
* return session
* },
* }
* })
* ```
* :::
*
* :::info
* We are advocates of TypeScript, as it will help you catch errors at build-time, before your users do. 😉
* :::
*
* ## Resources
*
* - [TypeScript - The Basics](https://www.typescriptlang.org/docs/handbook/2/basic-types.html)
* - [Extending built-in types](https://authjs.dev/getting-started/typescript#module-augmentation)
*
* @module types
*/
import type { CookieSerializeOptions } from "cookie"
import type {
OAuth2TokenEndpointResponse,
OpenIDTokenEndpointResponse,
} from "oauth4webapi"
import type { Adapter, AdapterUser } from "./adapters.js"
import { AuthConfig } from "./index.js"
import type { JWT, JWTOptions } from "./jwt.js"
import type { Cookie } from "./lib/cookie.js"
import type { LoggerInstance } from "./lib/utils/logger.js"
import type {
CredentialInput,
CredentialsConfig,
EmailConfig,
OAuthConfigInternal,
OIDCConfigInternal,
ProviderType,
} from "./providers/index.js"
export type { AuthConfig } from "./index.js"
export type { LoggerInstance }
export type Awaitable<T> = T | PromiseLike<T>
/**
* Change the theme of the built-in pages.
*
* [Documentation](https://authjs.dev/reference/configuration/auth-config#theme) |
* [Pages](https://authjs.dev/guides/basics/pages)
*/
export interface Theme {
colorScheme?: "auto" | "dark" | "light"
logo?: string
brandColor?: string
buttonText?: string
}
/**
* Different tokens returned by OAuth Providers.
* Some of them are available with different casing,
* but they refer to the same value.
*/
export type TokenSet = Partial<
OAuth2TokenEndpointResponse | OpenIDTokenEndpointResponse
> & {
/**
* Date of when the `access_token` expires in seconds.
* This value is calculated from the `expires_in` value.
*
* @see https://www.ietf.org/rfc/rfc6749.html#section-4.2.2
*/
expires_at?: number
}
/**
* Usually contains information about the provider being used
* and also extends `TokenSet`, which is different tokens returned by OAuth Providers.
*/
export interface Account extends Partial<OpenIDTokenEndpointResponse> {
/** Provider's id for this account. Eg.: "google" */
provider: string
/**
* This value depends on the type of the provider being used to create the account.
* - oauth/oidc: The OAuth account's id, returned from the `profile()` callback.
* - email: The user's email address.
* - credentials: `id` returned from the `authorize()` callback
*/
providerAccountId: string
/** Provider's type for this account */
type: ProviderType
/**
* id of the user this account belongs to
*
* @see https://authjs.dev/reference/adapters#user
*/
userId?: string
/**
* Calculated value based on {@link OAuth2TokenEndpointResponse.expires_in}.
*
* It is the absolute timestamp (in seconds) when the {@link OAuth2TokenEndpointResponse.access_token} expires.
*
* This value can be used for implementing token rotation together with {@link OAuth2TokenEndpointResponse.refresh_token}.
*
* @see https://authjs.dev/guides/basics/refresh-token-rotation#database-strategy
* @see https://www.rfc-editor.org/rfc/rfc6749#section-5.1
*/
expires_at?: number
}
/**
* The user info returned from your OAuth provider.
*
* @see https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
*/
export interface Profile {
sub?: string | null
name?: string | null
given_name?: string | null
family_name?: string | null
middle_name?: string | null
nickname?: string | null
preferred_username?: string | null
profile?: string | null
picture?: string | null | any
website?: string | null
email?: string | null
email_verified?: boolean | null
gender?: string | null
birthdate?: string | null
zoneinfo?: string | null
locale?: string | null
phone_number?: string | null
updated_at?: Date | string | number | null
address?: {
formatted?: string | null
street_address?: string | null
locality?: string | null
region?: string | null
postal_code?: string | null
country?: string | null
} | null
[claim: string]: unknown
}
/** [Documentation](https://authjs.dev/guides/basics/callbacks) */
export interface CallbacksOptions<P = Profile, A = Account> {
/**
* Control whether a user is allowed to sign in or not.
* Returning `true` continues the sign-in flow, while
* returning `false` redirects to the {@link PagesOptions.error error page}.
* The `error` {@link ErrorPageParam parameter} is set to `AccessDenied`.
*
* Unhandled errors are redirected to the error page
* The `error` parameter is set to `Configuration`.
* an `AuthorizedCallbackError` is logged on the server.
*
* @see https://authjs.dev/reference/errors#authorizedcallbackerror
* @todo rename to `authorized`
*/
signIn: (params: {
user: User | AdapterUser
account: A | null
/**
* If OAuth provider is used, it contains the full
* OAuth profile returned by your provider.
*/
profile?: P
/**
* If Email provider is used, on the first call, it contains a
* `verificationRequest: true` property to indicate it is being triggered in the verification request flow.
* When the callback is invoked after a user has clicked on a sign in link,
* this property will not be present. You can check for the `verificationRequest` property
* to avoid sending emails to addresses or domains on a blocklist or to only explicitly generate them
* for email address in an allow list.
*/
email?: {
verificationRequest?: boolean
}
/** If Credentials provider is used, it contains the user credentials */
credentials?: Record<string, CredentialInput>
}) => Awaitable<boolean>
/**
* This callback is called anytime the user is redirected to a callback URL (e.g. on signin or signout).
* By default only URLs on the same URL as the site are allowed,
* you can use this callback to customise that behaviour.
*
* [Documentation](https://authjs.dev/guides/basics/callbacks#redirect-callback)
*/
redirect: (params: {
/** URL provided as callback URL by the client */
url: string
/** Default base URL of site (can be used as fallback) */
baseUrl: string
}) => Awaitable<string>
/**
* This callback is called whenever a session is checked.
* (Eg.: invoking the `/api/session` endpoint, using `useSession` or `getSession`)
*
* ⚠ By default, only a subset (email, name, image)
* of the token is returned for increased security.
*
* If you want to make something available you added to the token through the `jwt` callback,
* you have to explicitly forward it here to make it available to the client.
*
* @see [`jwt` callback](https://authjs.dev/reference/core/types#jwt)
*/
session: (
params:
| {
session: Session
/** Available when {@link AuthConfig.session} is set to `strategy: "jwt"` */
token: JWT
/** Available when {@link AuthConfig.session} is set to `strategy: "database"`. */
user: AdapterUser
} & {
/**
* Available when using {@link AuthConfig.session} `strategy: "database"` and an update is triggered for the session.
*
* :::note
* You should validate this data before using it.
* :::
*/
newSession: any
trigger: "update"
}
) => Awaitable<Session | DefaultSession>
/**
* This callback is called whenever a JSON Web Token is created (i.e. at sign in)
* or updated (i.e whenever a session is accessed in the client).
* Its content is forwarded to the `session` callback,
* where you can control what should be returned to the client.
* Anything else will be kept from your front-end.
*
* The JWT is encrypted by default.
*
* [Documentation](https://next-auth.js.org/configuration/callbacks#jwt-callback) |
* [`session` callback](https://next-auth.js.org/configuration/callbacks#session-callback)
*/
jwt: (params: {
/**
* When `trigger` is `"signIn"` or `"signUp"`, it will be a subset of {@link JWT},
* `name`, `email` and `image` will be included.
*
* Otherwise, it will be the full {@link JWT} for subsequent calls.
*/
token: JWT
/**
* Either the result of the {@link OAuthConfig.profile} or the {@link CredentialsConfig.authorize} callback.
* @note available when `trigger` is `"signIn"` or `"signUp"`.
*
* Resources:
* - [Credentials Provider](https://authjs.dev/reference/core/providers_credentials)
* - [User database model](https://authjs.dev/reference/adapters#user)
*/
user: User | AdapterUser
/**
* Contains information about the provider that was used to sign in.
* Also includes {@link TokenSet}
* @note available when `trigger` is `"signIn"` or `"signUp"`
*/
account: A | null
/**
* The OAuth profile returned from your provider.
* (In case of OIDC it will be the decoded ID Token or /userinfo response)
* @note available when `trigger` is `"signIn"`.
*/
profile?: P
/**
* Check why was the jwt callback invoked. Possible reasons are:
* - user sign-in: First time the callback is invoked, `user`, `profile` and `account` will be present.
* - user sign-up: a user is created for the first time in the database (when {@link AuthConfig.session}.strategy is set to `"database"`)
* - update event: Triggered by the [`useSession().update`](https://next-auth.js.org/getting-started/client#update-session) method.
* In case of the latter, `trigger` will be `undefined`.
*/
trigger?: "signIn" | "signUp" | "update"
/** @deprecated use `trigger === "signUp"` instead */
isNewUser?: boolean
/**
* When using {@link AuthConfig.session} `strategy: "jwt"`, this is the data
* sent from the client via the [`useSession().update`](https://next-auth.js.org/getting-started/client#update-session) method.
*
* ⚠ Note, you should validate this data before using it.
*/
session?: any
}) => Awaitable<JWT | null>
}
/** [Documentation](https://authjs.dev/reference/configuration/auth-config#cookies) */
export interface CookieOption {
name: string
options: CookieSerializeOptions
}
/** [Documentation](https://authjs.dev/reference/configuration/auth-config#cookies) */
export interface CookiesOptions {
sessionToken: CookieOption
callbackUrl: CookieOption
csrfToken: CookieOption
pkceCodeVerifier: CookieOption
state: CookieOption
nonce: CookieOption
}
/**
* The various event callbacks you can register for from next-auth
*
* [Documentation](https://authjs.dev/guides/basics/events)
*/
export interface EventCallbacks {
/**
* If using a `credentials` type auth, the user is the raw response from your
* credential provider.
* For other providers, you'll get the User object from your adapter, the account,
* and an indicator if the user was new to your Adapter.
*/
signIn: (message: {
user: User
account: Account | null
profile?: Profile
isNewUser?: boolean
}) => Awaitable<void>
/**
* The message object will contain one of these depending on
* if you use JWT or database persisted sessions:
* - `token`: The JWT for this session.
* - `session`: The session object from your adapter that is being ended.
*/
signOut: (
message:
| { session: Awaited<ReturnType<Required<Adapter>["deleteSession"]>> }
| { token: Awaited<ReturnType<JWTOptions["decode"]>> }
) => Awaitable<void>
createUser: (message: { user: User }) => Awaitable<void>
updateUser: (message: { user: User }) => Awaitable<void>
linkAccount: (message: {
user: User | AdapterUser
account: Account
profile: User | AdapterUser
}) => Awaitable<void>
/**
* The message object will contain one of these depending on
* if you use JWT or database persisted sessions:
* - `token`: The JWT for this session.
* - `session`: The session object from your adapter.
*/
session: (message: { session: Session; token: JWT }) => Awaitable<void>
}
export type EventType = keyof EventCallbacks
/** TODO: Check if all these are used/correct */
export type ErrorPageParam = "Configuration" | "AccessDenied" | "Verification"
/** TODO: Check if all these are used/correct */
export type SignInPageErrorParam =
| "Signin"
| "OAuthSignin"
| "OAuthCallbackError"
| "OAuthCreateAccount"
| "EmailCreateAccount"
| "Callback"
| "OAuthAccountNotLinked"
| "EmailSignin"
| "CredentialsSignin"
| "SessionRequired"
export interface PagesOptions {
/**
* The path to the sign in page.
*
* The optional "error" query parameter is set to
* one of the {@link SignInPageErrorParam available} values.
*
* @default "/signin"
*/
signIn: string
signOut: string
/**
* The path to the error page.
*
* The optional "error" query parameter is set to
* one of the {@link ErrorPageParam available} values.
*
* @default "/error"
*/
error: string
verifyRequest: string
/** If set, new users will be directed here on first sign in */
newUser: string
}
type ISODateString = string
export interface DefaultSession {
user?: User
expires: ISODateString
}
/**
* Returned by `useSession`, `getSession`, returned by the `session` callback
* and also the shape received as a prop on the `SessionProvider` React Context
*
* [`useSession`](https://authjs.dev/reference/react/#usesession) |
* [`getSession`](https://authjs.dev/reference/utilities#getsession) |
* [`SessionProvider`](https://authjs.dev/reference/react#sessionprovider) |
* [`session` callback](https://authjs.dev/guides/basics/callbacks#jwt-callback)
*/
export interface Session extends DefaultSession {}
/**
* The shape of the returned object in the OAuth providers' `profile` callback,
* available in the `jwt` and `session` callbacks,
* or the second parameter of the `session` callback, when using a database.
*
* [`signIn` callback](https://authjs.dev/guides/basics/callbacks#sign-in-callback) |
* [`session` callback](https://authjs.dev/guides/basics/callbacks#jwt-callback) |
* [`jwt` callback](https://authjs.dev/guides/basics/callbacks#jwt-callback) |
* [`profile` OAuth provider callback](https://authjs.dev/guides/providers/custom-provider)
*/
export interface User {
id: string
name?: string | null
email?: string | null
image?: string | null
}
// Below are types that are only supposed be used by next-auth internally
/** @internal */
export type InternalProvider<T = ProviderType> = (T extends "oauth"
? OAuthConfigInternal<any>
: T extends "oidc"
? OIDCConfigInternal<any>
: T extends "email"
? EmailConfig
: T extends "credentials"
? CredentialsConfig
: never) & {
signinUrl: string
/** @example `"https://example.com/api/auth/callback/id"` */
callbackUrl: string
}
/**
* Supported actions by Auth.js. Each action map to a REST API endpoint.
* Some actions have a `GET` and `POST` variant, depending on if the action
* changes the state of the server.
*
* - **`"callback"`**:
* - **`GET`**: Handles the callback from an [OAuth provider](https://authjs.dev/reference/core/providers_oauth).
* - **`POST`**: Handles the callback from a [Credentials provider](https://authjs.dev/reference/core/providers_credentials).
* - **`"csrf"`**: Returns the raw CSRF token, which is saved in a cookie (encrypted).
* It is used for CSRF protection, implementing the [double submit cookie](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#double-submit-cookie) technique.
* :::note
* Some frameworks have built-in CSRF protection and can therefore disable this action. In this case, the corresponding endpoint will return a 404 response. Read more at [`skipCSRFCheck`](https://authjs.dev/reference/core#skipcsrfcheck).
* _⚠ We don't recommend manually disabling CSRF protection, unless you know what you're doing._
* :::
* - **`"error"`**: Renders the built-in error page.
* - **`"providers"`**: Returns a client-safe list of all configured providers.
* - **`"session"`**:
* - **`GET**`: Returns the user's session if it exists, otherwise `null`.
* - **`POST**`: Updates the user's session and returns the updated session.
* - **`"signin"`**:
* - **`GET`**: Renders the built-in sign-in page.
* - **`POST`**: Initiates the sign-in flow.
* - **`"signout"`**:
* - **`GET`**: Renders the built-in sign-out page.
* - **`POST`**: Initiates the sign-out flow. This will invalidate the user's session (deleting the cookie, and if there is a session in the database, it will be deleted as well).
* - **`"verify-request"`**: Renders the built-in verification request page.
*/
export type AuthAction =
| "callback"
| "csrf"
| "error"
| "providers"
| "session"
| "signin"
| "signout"
| "verify-request"
/** @internal */
export interface RequestInternal {
url: URL
method: "GET" | "POST"
cookies?: Partial<Record<string, string>>
headers?: Record<string, any>
query?: Record<string, any>
body?: Record<string, any>
action: AuthAction
providerId?: string
error?: string
}
/** @internal */
export interface ResponseInternal<
Body extends string | Record<string, any> | any[] | null = any
> {
status?: number
headers?: Headers | HeadersInit
body?: Body
redirect?: string
cookies?: Cookie[]
}
/** @internal */
export interface InternalOptions<TProviderType = ProviderType> {
providers: InternalProvider[]
url: URL
action: AuthAction
provider: InternalProvider<TProviderType>
csrfToken?: string
csrfTokenVerified?: boolean
secret: string
theme: Theme
debug: boolean
logger: LoggerInstance
session: NonNullable<Required<AuthConfig["session"]>>
pages: Partial<PagesOptions>
jwt: JWTOptions
events: Partial<EventCallbacks>
adapter: Required<Adapter> | undefined
callbacks: CallbacksOptions
cookies: CookiesOptions
callbackUrl: string
/**
* If true, the OAuth callback is being proxied by the server to the original URL.
* See also {@link OAuthConfigInternal.redirectProxyUrl}.
*/
isOnRedirectProxy: boolean
}