From 01d9a81f5551540d13dae67f3a6e977b2262899c Mon Sep 17 00:00:00 2001 From: Zack Sheppard Date: Sun, 25 Apr 2021 17:44:49 +0100 Subject: [PATCH 01/16] Constrain the adapters type generics more accurately --- types/adapters.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/adapters.d.ts b/types/adapters.d.ts index 1ba676e52f..a502e139ce 100644 --- a/types/adapters.d.ts +++ b/types/adapters.d.ts @@ -1,6 +1,6 @@ import { AppOptions } from "./internals" import { User, Profile, Session } from "." -import { EmailConfig, SendVerificationRequest } from "./providers" +import { EmailConfig } from "./providers" import { ConnectionOptions } from "typeorm" /** Legacy */ From f5ca3c1272765d7f4da9a09417802439a29efcfb Mon Sep 17 00:00:00 2001 From: Zack Sheppard Date: Sun, 25 Apr 2021 17:45:01 +0100 Subject: [PATCH 02/16] Add types for the incoming messages to events callbacks --- types/index.d.ts | 85 ++++++++++++++++++++++++++++++-------- types/tests/server.test.ts | 28 +++++++------ 2 files changed, 83 insertions(+), 30 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 0adaee1301..4e97e19141 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,9 +1,14 @@ -// Minimum TypeScript Version: 3.5 +// Minimum TypeScript Version: 3.6 /// import { ConnectionOptions } from "typeorm" -import { Adapter } from "./adapters" +import { + Adapter, + Session as AdapterSession, + Profile as AdapterProfile, + VerificationRequest, +} from "./adapters" import { JWTOptions, JWT } from "./jwt" import { AppProviders } from "./providers" import { @@ -18,7 +23,12 @@ import { * * [Documentation](https://next-auth.js.org/configuration/options#options) */ -export interface NextAuthOptions { +export interface NextAuthOptions< + TUser extends User = User, + TProfile extends AdapterProfile = AdapterProfile, + TSession extends AdapterSession = AdapterSession, + TVerificationRequest extends VerificationRequest = VerificationRequest +> { /** * An array of authentication providers for signing in * (e.g. Google, Facebook, Twitter, GitHub, Email, etc) in any order. @@ -111,7 +121,9 @@ export interface NextAuthOptions { * * [Documentation](https://next-auth.js.org/configuration/options#events) | [Events documentation](https://next-auth.js.org/configuration/events) */ - events?: EventsOptions + events?: Partial< + JWTEventOptions | SessionEventsOptions + > /** * By default NextAuth.js uses a database adapter that uses TypeORM and supports MySQL, MariaDB, Postgres and MongoDB and SQLite databases. * An alternative adapter that uses Prisma, which currently supports MySQL, MariaDB and Postgres, is also included. @@ -127,7 +139,7 @@ export interface NextAuthOptions { * [Default adapter](https://next-auth.js.org/schemas/adapters#typeorm-adapter) | * [Community adapters](https://github.com/nextauthjs/adapters) */ - adapter?: Adapter + adapter?: Adapter /** * Set debug to true to enable debug messages for authentication and database operations. * * **Default value**: `false` @@ -342,20 +354,59 @@ export interface CookiesOptions { } /** [Documentation](https://next-auth.js.org/configuration/events) */ -export type EventType = - | "signIn" - | "signOut" - | "createUser" - | "updateUser" - | "linkAccount" - | "session" - | "error" +export type EventCallback = ( + message: MessageType +) => Promise -/** [Documentation](https://next-auth.js.org/configuration/events) */ -export type EventCallback = (message: any) => Promise +export interface SessionEventMessage { + session: Session & Record + jwt?: JWT +} -/** [Documentation](https://next-auth.js.org/configuration/events) */ -export type EventsOptions = Partial> +/** + * 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. + */ +export interface SignInEventMessage { + user: TUser + account: Record + isNewUser?: boolean +} + +export interface LinkAccountEventMessage { + user: TUser + providerAccount: Record +} + +export interface EventOptions { + signIn: EventCallback> + signOut: EventCallback + createUser: EventCallback + updateUser: EventCallback + linkAccount: EventCallback> + session: EventCallback + error: EventCallback +} + +export interface JWTEventOptions extends EventOptions { + signOut: EventCallback> + session: EventCallback<{ + session: Session & Record + jwt: JWT + }> +} + +export interface SessionEventsOptions + extends EventOptions { + signOut: EventCallback + session: EventCallback<{ + session: Session & Record + }> +} + +export type EventType = keyof EventOptions /** [Documentation](https://next-auth.js.org/configuration/pages) */ export interface PagesOptions { diff --git a/types/tests/server.test.ts b/types/tests/server.test.ts index 839e16ecd8..63ae2d97cf 100644 --- a/types/tests/server.test.ts +++ b/types/tests/server.test.ts @@ -1,12 +1,7 @@ -import Providers, { - AppProvider, - EmailConfig, - OAuthConfig, -} from "next-auth/providers" -import { Adapter, AdapterInstance } from "next-auth/adapters" +import Providers, { OAuthConfig } from "next-auth/providers" +import { Adapter } 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 "internals/utils" import { AppOptions } from "internals" @@ -171,22 +166,29 @@ const allConfig: NextAuthTypes.NextAuthOptions = { }, }, events: { - async signIn(message) { + async signIn( + message: NextAuthTypes.SignInEventMessage + ) { return undefined }, - async signOut(message) { + async signOut(message: NextAuthTypes.Session | null) { return undefined }, - async createUser(message) { + async createUser(message: NextAuthTypes.User) { return undefined }, - async linkAccount(message) { + async updateUser(message: NextAuthTypes.User) { return undefined }, - async session(message) { + async linkAccount( + message: NextAuthTypes.LinkAccountEventMessage + ) { return undefined }, - async error(message) { + async session(message: NextAuthTypes.Session) { + return undefined + }, + async error(message: any) { return undefined }, }, From 6ef0be88dccd654b75d098d811c3b005f6b19e64 Mon Sep 17 00:00:00 2001 From: Zack Sheppard Date: Thu, 29 Apr 2021 00:03:19 +0100 Subject: [PATCH 03/16] Code review comments from @lluia --- types/index.d.ts | 57 +++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 4e97e19141..7a0f272645 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -122,7 +122,7 @@ export interface NextAuthOptions< * [Documentation](https://next-auth.js.org/configuration/options#events) | [Events documentation](https://next-auth.js.org/configuration/events) */ events?: Partial< - JWTEventOptions | SessionEventsOptions + JWTEventCallbacks | SessionEventCallbacks > /** * By default NextAuth.js uses a database adapter that uses TypeORM and supports MySQL, MariaDB, Postgres and MongoDB and SQLite databases. @@ -354,15 +354,10 @@ export interface CookiesOptions { } /** [Documentation](https://next-auth.js.org/configuration/events) */ -export type EventCallback = ( +export type EventCallback = ( message: MessageType ) => Promise -export interface SessionEventMessage { - session: Session & Record - jwt?: JWT -} - /** * If using a `credentials` type auth, the user is the raw response from your * credential provider. @@ -380,33 +375,51 @@ export interface LinkAccountEventMessage { providerAccount: Record } -export interface EventOptions { +/** + * The various event callbacks you can register for from next-auth + */ +export interface EventCallbacks< + TUser = unknown, + TSignOutMessage = unknown, + TSessionMessage = unknown +> { signIn: EventCallback> - signOut: EventCallback + signOut: EventCallback createUser: EventCallback updateUser: EventCallback linkAccount: EventCallback> - session: EventCallback + session: EventCallback error: EventCallback } -export interface JWTEventOptions extends EventOptions { - signOut: EventCallback> - session: EventCallback<{ +/** + * The event callbacks will take this form if you are using JWTs: + * signOut will receive the JWT and session will receive the session and JWT. + */ +export type JWTEventCallbacks = EventCallbacks< + TUser, + JWT & Record, + { session: Session & Record jwt: JWT - }> -} + } +> -export interface SessionEventsOptions - extends EventOptions { - signOut: EventCallback - session: EventCallback<{ +/** + * The event callbacks will take this form if you are using Sessions + * and not using JWTs: + * signOut will receive the underlying db adapter's session object, and session + * will receive the NextAuth client session with extra data. + */ +export type SessionEventCallbacks = EventCallbacks< + TUser, + TAdapterSession | null, + { session: Session & Record - }> -} + } +> -export type EventType = keyof EventOptions +export type EventType = keyof EventCallbacks /** [Documentation](https://next-auth.js.org/configuration/pages) */ export interface PagesOptions { From c9d3fa192ed7d25124e1bbda3a4d7da5377e13fe Mon Sep 17 00:00:00 2001 From: Zack Sheppard Date: Thu, 29 Apr 2021 00:09:44 +0100 Subject: [PATCH 04/16] Rebase from trunk and fix merge conflicts --- types/index.d.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 7a0f272645..7f61154048 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -3,12 +3,7 @@ /// import { ConnectionOptions } from "typeorm" -import { - Adapter, - Session as AdapterSession, - Profile as AdapterProfile, - VerificationRequest, -} from "./adapters" +import { Adapter } from "./adapters" import { JWTOptions, JWT } from "./jwt" import { AppProviders } from "./providers" import { @@ -25,9 +20,8 @@ import { */ export interface NextAuthOptions< TUser extends User = User, - TProfile extends AdapterProfile = AdapterProfile, - TSession extends AdapterSession = AdapterSession, - TVerificationRequest extends VerificationRequest = VerificationRequest + TProfile extends Profile = Profile, + TSession extends Session = Session > { /** * An array of authentication providers for signing in @@ -139,7 +133,7 @@ export interface NextAuthOptions< * [Default adapter](https://next-auth.js.org/schemas/adapters#typeorm-adapter) | * [Community adapters](https://github.com/nextauthjs/adapters) */ - adapter?: Adapter + adapter?: Adapter /** * Set debug to true to enable debug messages for authentication and database operations. * * **Default value**: `false` From 3178f08f4b7d2468b8cb626b05ac9c83f68a0711 Mon Sep 17 00:00:00 2001 From: Zack Sheppard Date: Thu, 29 Apr 2021 00:58:38 +0100 Subject: [PATCH 05/16] Update documentation --- www/docs/configuration/events.md | 71 +++++++++++++++++---- www/docs/configuration/options.md | 102 ++++++++++++++---------------- 2 files changed, 106 insertions(+), 67 deletions(-) diff --git a/www/docs/configuration/events.md b/www/docs/configuration/events.md index 2a0e9ea308..791e7e23a9 100644 --- a/www/docs/configuration/events.md +++ b/www/docs/configuration/events.md @@ -7,17 +7,60 @@ Events are asynchronous functions that do not return a response, they are useful You can specify a handler for any of these events below, for debugging or for an audit log. -```js title="pages/api/auth/[...nextauth].js" -... - events: { - async signIn(message) { /* on successful sign in */ }, - async signOut(message) { /* on signout */ }, - async createUser(message) { /* user created */ }, - async linkAccount(message) { /* account linked to a user */ }, - async session(message) { /* session is active */ }, - async error(message) { /* error in authentication flow */ } - } -... -``` - -The content of the message object varies depending on the flow (e.g. OAuth or Email authentication flow, JWT or database sessions, etc) but typically contains a user object and/or contents of the JSON Web Token and other information relevant to the event. +:::note +Execution of your auth API will be blocked by an `await` on your event handler. If your event handler starts any burdensome work it should not block its own promise on that work. +::: + +## Events + +### signIn + +Sent on successful sign in. + +The message will be an object and contain: + +- `user` (from your adapter or from the provider if a `credentials` type provider) +- `account` (from your adapter or the provider) +- `isNewUser` (whether your adapter had a user for this account already) + +### signOut + +Sent when the user signs out. + +The message object is the JWT, if using them, or the adapter session object for the session that is being ended. + +### createUser + +Sent when the adapter is told to create a new user. + +The message object will be the user. + +### updateUser + +Sent when the adapter is told to update an existing user. Currently this is only sent when the user verifies their email address. + +The message object will be the user. + +### linkAccount + +Sent when an account in a given provider is linked to a user in our userbase. For example, when a user signs up with Twitter or when an existing user links their Google account. + +The message will be an object and contain: + +- `user`: The user object from your adapter +- `providerAccount`: The object returned from the provider. + +### session + +Sent at the end of a request for the current session. + +The message will be an object and contain: + +- `session`: The session object from your adapter +- `jwt`: If using JWT, the token for this session. + +### error + +Sent when an error occurs + +The message could be any object relevant to describing the error. diff --git a/www/docs/configuration/options.md b/www/docs/configuration/options.md index b590fa2d65..8352e1fd4b 100644 --- a/www/docs/configuration/options.md +++ b/www/docs/configuration/options.md @@ -5,7 +5,7 @@ title: Options ## Environment Variables -### NEXTAUTH_URL +### NEXTAUTH_URL When deploying to production, set the `NEXTAUTH_URL` environment variable to the canonical URL of your site. @@ -37,10 +37,10 @@ Options are passed to NextAuth.js when initializing it in an API route. ### providers -* **Default value**: `[]` -* **Required**: *Yes* +- **Default value**: `[]` +- **Required**: _Yes_ -#### Description +#### Description An array of authentication providers for signing in (e.g. Google, Facebook, Twitter, GitHub, Email, etc) in any order. This can be one of the built-in providers or an object with a custom provider. @@ -50,10 +50,10 @@ See the [providers documentation](/configuration/providers) for a list of suppor ### database -* **Default value**: `null` -* **Required**: *No (unless using email provider)* +- **Default value**: `null` +- **Required**: _No (unless using email provider)_ -#### Description +#### Description [A database connection string or configuration object.](/configuration/databases) @@ -61,8 +61,8 @@ See the [providers documentation](/configuration/providers) for a list of suppor ### secret -* **Default value**: `string` (*SHA hash of the "options" object*) -* **Required**: *No - but strongly recommended!* +- **Default value**: `string` (_SHA hash of the "options" object_) +- **Required**: _No - but strongly recommended!_ #### Description @@ -76,8 +76,8 @@ The default behaviour is volatile, and it is strongly recommended you explicitly ### session -* **Default value**: `object` -* **Required**: *No* +- **Default value**: `object` +- **Required**: _No_ #### Description @@ -90,14 +90,14 @@ session: { // Use JSON Web Tokens for session instead of database sessions. // This option can be used with or without a database for users/accounts. // Note: `jwt` is automatically set to `true` if no database is specified. - jwt: false, - + jwt: false, + // Seconds - How long until an idle session expires and is no longer valid. maxAge: 30 * 24 * 60 * 60, // 30 days - + // Seconds - Throttle how frequently to write to database to extend a session. // Use it to limit write operations. Set to 0 to always update the database. - // Note: This option is ignored if using JSON Web Tokens + // Note: This option is ignored if using JSON Web Tokens updateAge: 24 * 60 * 60, // 24 hours } ``` @@ -106,8 +106,8 @@ session: { ### jwt -* **Default value**: `object` -* **Required**: *No* +- **Default value**: `object` +- **Required**: _No_ #### Description @@ -124,18 +124,15 @@ jwt: { // 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: "", @@ -143,7 +140,6 @@ jwt: { // 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 }) {}, @@ -168,13 +164,13 @@ An example JSON Web Token contains a payload like this: You can use the built-in `getToken()` helper method to verify and decrypt the token, like this: ```js -import jwt from 'next-auth/jwt' +import jwt from "next-auth/jwt" const secret = process.env.JWT_SECRET export default async (req, res) => { const token = await jwt.getToken({ req, secret }) - console.log('JSON Web Token', token) + console.log("JSON Web Token", token) res.end() } ``` @@ -185,10 +181,10 @@ _For convenience, this helper function is also able to read and decode tokens pa The getToken() helper requires the following options: -* `req` - (object) Request object -* `secret` - (string) JWT Secret +- `req` - (object) Request object +- `secret` - (string) JWT Secret -You must also pass *any options configured on the `jwt` option* to the helper. +You must also pass _any options configured on the `jwt` option_ to the helper. e.g. Including custom session `maxAge` and custom signing and/or encryption keys or options @@ -196,15 +192,15 @@ e.g. Including custom session `maxAge` and custom signing and/or encryption keys It also supports the following options: -* `secureCookie` - (boolean) Use secure prefixed cookie name +- `secureCookie` - (boolean) Use secure prefixed cookie name By default, the helper function will attempt to determine if it should use the secure prefixed cookie (e.g. `true` in production and `false` in development, unless NEXTAUTH_URL contains an HTTPS URL). -* `cookieName` - (string) Session token cookie name +- `cookieName` - (string) Session token cookie name The `secureCookie` option is ignored if `cookieName` is explicitly specified. -* `raw` - (boolean) Get raw token (not decoded) +- `raw` - (boolean) Get raw token (not decoded) If set to `true` returns the raw token without decrypting or verifying it. @@ -216,8 +212,8 @@ The JWT is stored in the Session Token cookie, the same cookie used for tokens w ### pages -* **Default value**: `{}` -* **Required**: *No* +- **Default value**: `{}` +- **Required**: _No_ #### Description @@ -225,7 +221,7 @@ Specify URLs to be used if you want to create custom sign in, sign out and error Pages specified will override the corresponding built-in page. -*For example:* +_For example:_ ```js pages: { @@ -243,8 +239,8 @@ See the documentation for the [pages option](/configuration/pages) for more info ### callbacks -* **Default value**: `object` -* **Required**: *No* +- **Default value**: `object` +- **Required**: _No_ #### Description @@ -277,8 +273,8 @@ See the [callbacks documentation](/configuration/callbacks) for more information ### events -* **Default value**: `object` -* **Required**: *No* +- **Default value**: `object` +- **Required**: _No_ #### Description @@ -286,27 +282,26 @@ Events are asynchronous functions that do not return a response, they are useful You can specify a handler for any of these events below - e.g. for debugging or to create an audit log. -The content of the message object varies depending on the flow (e.g. OAuth or Email authentication flow, JWT or database sessions, etc), but typically contains a user object and/or contents of the JSON Web Token and other information relevant to the event. +The content of the message object varies depending on the flow (e.g. OAuth or Email authentication flow, JWT or database sessions, etc). See the [events documentation](/configuration/events) for more information on the form of each message object and how to use the events functions. ```js events: { async signIn(message) { /* on successful sign in */ }, async signOut(message) { /* on signout */ }, async createUser(message) { /* user created */ }, - async linkAccount(message) { /* account linked to a user */ }, + async updateUser(message) { /* user updated - e.g. their email was verified */ }, + async linkAccount(message) { /* account (e.g. Twitter) linked to a user */ }, async session(message) { /* session is active */ }, async error(message) { /* error in authentication flow */ } } ``` -See the [events documentation](/configuration/events) for more information on how to use the events functions. - --- ### adapter -* **Default value**: *Adapter.Default()* -* **Required**: *No* +- **Default value**: _Adapter.Default()_ +- **Required**: _No_ #### Description @@ -324,8 +319,8 @@ If the `adapter` option is specified it overrides the `database` option, only sp ### debug -* **Default value**: `false` -* **Required**: *No* +- **Default value**: `false` +- **Required**: _No_ #### Description @@ -335,14 +330,15 @@ Set debug to `true` to enable debug messages for authentication and database ope ### logger -* **Default value**: `console` -* **Required**: *No* +- **Default value**: `console` +- **Required**: _No_ #### Description Override any of the logger levels (`undefined` levels will use the built-in logger), and intercept logs in NextAuth. You can use this to send NextAuth logs to a third-party logging service. Example: + ```js title="/pages/api/auth/[...nextauth].js" import log from "logging-service" @@ -371,8 +367,8 @@ If the `debug` level is defined by the user, it will be called regardless of the ### theme -* **Default value**: `"auto"` -* **Required**: *No* +- **Default value**: `"auto"` +- **Required**: _No_ #### Description @@ -388,8 +384,8 @@ Advanced options are passed the same way as basic options, but may have complex ### useSecureCookies -* **Default value**: `true` for HTTPS sites / `false` for HTTP sites -* **Required**: *No* +- **Default value**: `true` for HTTPS sites / `false` for HTTP sites +- **Required**: _No_ #### Description @@ -404,15 +400,15 @@ Properties on any custom `cookies` that are specified override this option. ::: :::warning -Setting this option to *false* in production is a security risk and may allow sessions to hijacked if used in production. It is intended to support development and testing. Using this option is not recommended. +Setting this option to _false_ in production is a security risk and may allow sessions to hijacked if used in production. It is intended to support development and testing. Using this option is not recommended. ::: --- ### cookies -* **Default value**: `{}` -* **Required**: *No* +- **Default value**: `{}` +- **Required**: _No_ #### Description From e0c5c86da43106d6c11c28741284e6f4f89c50a9 Mon Sep 17 00:00:00 2001 From: Zack Sheppard Date: Thu, 29 Apr 2021 01:19:23 +0100 Subject: [PATCH 06/16] Rip out generics --- types/index.d.ts | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 7f61154048..4422fc68ed 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -18,11 +18,7 @@ import { * * [Documentation](https://next-auth.js.org/configuration/options#options) */ -export interface NextAuthOptions< - TUser extends User = User, - TProfile extends Profile = Profile, - TSession extends Session = Session -> { +export interface NextAuthOptions { /** * An array of authentication providers for signing in * (e.g. Google, Facebook, Twitter, GitHub, Email, etc) in any order. @@ -115,9 +111,7 @@ export interface NextAuthOptions< * * [Documentation](https://next-auth.js.org/configuration/options#events) | [Events documentation](https://next-auth.js.org/configuration/events) */ - events?: Partial< - JWTEventCallbacks | SessionEventCallbacks - > + events?: Partial /** * By default NextAuth.js uses a database adapter that uses TypeORM and supports MySQL, MariaDB, Postgres and MongoDB and SQLite databases. * An alternative adapter that uses Prisma, which currently supports MySQL, MariaDB and Postgres, is also included. @@ -133,7 +127,7 @@ export interface NextAuthOptions< * [Default adapter](https://next-auth.js.org/schemas/adapters#typeorm-adapter) | * [Community adapters](https://github.com/nextauthjs/adapters) */ - adapter?: Adapter + adapter?: Adapter /** * Set debug to true to enable debug messages for authentication and database operations. * * **Default value**: `false` @@ -373,15 +367,14 @@ export interface LinkAccountEventMessage { * The various event callbacks you can register for from next-auth */ export interface EventCallbacks< - TUser = unknown, TSignOutMessage = unknown, TSessionMessage = unknown > { - signIn: EventCallback> + signIn: EventCallback> signOut: EventCallback - createUser: EventCallback - updateUser: EventCallback - linkAccount: EventCallback> + createUser: EventCallback + updateUser: EventCallback + linkAccount: EventCallback> session: EventCallback error: EventCallback } @@ -390,8 +383,7 @@ export interface EventCallbacks< * The event callbacks will take this form if you are using JWTs: * signOut will receive the JWT and session will receive the session and JWT. */ -export type JWTEventCallbacks = EventCallbacks< - TUser, +export type JWTEventCallbacks = EventCallbacks< JWT & Record, { session: Session & Record @@ -405,9 +397,8 @@ export type JWTEventCallbacks = EventCallbacks< * signOut will receive the underlying db adapter's session object, and session * will receive the NextAuth client session with extra data. */ -export type SessionEventCallbacks = EventCallbacks< - TUser, - TAdapterSession | null, +export type SessionEventCallbacks = EventCallbacks< + Session | null, { session: Session & Record } From 9ab4d38a415c14e9f8970c71928775568430e3d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Orb=C3=A1n?= Date: Sun, 2 May 2021 12:11:11 +0200 Subject: [PATCH 07/16] fix(build): export aliases from client (#1909) --- src/client/index.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/client/index.js b/src/client/index.js index 016b8d6685..d67e8f8361 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -355,6 +355,22 @@ function BroadcastChannel (name = 'nextauth.message') { } } + + +// Some methods are exported with more than one name. This provides some +// flexibility over how they can be invoked and backwards compatibility +// with earlier releases. These should be removed in a newer release, as it only +// creates problems for bundlers and adds confusion to users. TypeScript declarations +// will provide sufficient help when importing +export { + setOptions as options, + getSession as session, + getProviders as providers, + getCsrfToken as csrfToken, + signIn as signin, + signOut as signout +} + export default { getSession, getCsrfToken, From fcfad89059ac51e9a088d4e9e5fa02527b8f8c11 Mon Sep 17 00:00:00 2001 From: Lluis Agusti Date: Sun, 2 May 2021 22:07:08 +0200 Subject: [PATCH 08/16] docs(provider): update providers documentation (#1900) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs(providers): update providers documentation - delineate clearly the 3 provider types (oauth, email, credentials) - make each section structure consistent - update the option list for every provider type - use emojis * docs(providers): instructions on new provider types * docs(providers): remove emojis To stay consistent with the rest of our documentation, for now we should not emojis on the sections of our documentation pages. * docs(providers): reword sentence Co-authored-by: Balázs Orbán * docs(providers): add tip on overriding options * docs(providers): clarify `params` option usage * docs(providers): make names list inline Co-authored-by: Balázs Orbán --- www/docs/configuration/providers.md | 211 ++++++++++++++++++---------- www/src/css/index.css | 1 + www/src/css/providers.css | 9 ++ 3 files changed, 143 insertions(+), 78 deletions(-) create mode 100644 www/src/css/providers.css diff --git a/www/docs/configuration/providers.md b/www/docs/configuration/providers.md index a92956d96c..9afeb8dc17 100644 --- a/www/docs/configuration/providers.md +++ b/www/docs/configuration/providers.md @@ -3,59 +3,123 @@ id: providers title: Providers --- -Authentication Providers in NextAuth.js are services that can be used to sign in (OAuth, Email, etc). +Authentication Providers in **NextAuth.js** are services that can be used to sign in a user. -## Sign in with OAuth +There's four ways a user can be signed in: -NextAuth.js is designed to work with any OAuth service, it supports OAuth 1.0, 1.0A and 2.0 and has built-in support for many popular OAuth sign-in services. +- [Using a built-in OAuth Provider](#oauth-providers) (e.g Github, Twitter, Google, etc...) +- [Using a custom OAuth Provider](#-using-a-custom-provider) +- [Using Email](#email-provider) +- [Using Credentials](#credentials-provider) -### Built-in OAuth providers +:::note +NextAuth.js is designed to work with any OAuth service, it supports **OAuth 1.0**, **1.0A** and **2.0** and has built-in support for most popular sign-in services. +::: + +## OAuth Providers -
    +### Available providers + +
    {Object.entries(require("../../providers.json")) .filter(([key]) => !["email", "credentials"].includes(key)) .sort(([, a], [, b]) => a.localeCompare(b)) - .map(([key, name]) => -
  • {name}
  • + .map(([key, name]) => ( + + {name} + , + + ) + )} -
+ -### Using a built-in OAuth provider +### How to 1. Register your application at the developer portal of your provider. There are links above to the developer docs for most supported providers with details on how to register your application. 2. The redirect URI should follow this format: - ``` - [origin]/api/auth/callback/[provider] - ``` - For example, Twitter on `localhost` this would be: - ``` - http://localhost:3000/api/auth/callback/twitter - ``` + +``` +[origin]/api/auth/callback/[provider] +``` + +For example, Twitter on `localhost` this would be: + +``` +http://localhost:3000/api/auth/callback/twitter +``` + 3. Create a `.env` file at the root of your project and add the client ID and client secret. For Twitter this would be: - ``` - TWITTER_ID=YOUR_TWITTER_CLIENT_ID - TWITTER_SECRET=YOUR_TWITTER_CLIENT_SECRET - ``` +``` +TWITTER_ID=YOUR_TWITTER_CLIENT_ID +TWITTER_SECRET=YOUR_TWITTER_CLIENT_SECRET +``` 4. Now you can add the provider settings to the NextAuth options object. You can add as many OAuth providers as you like, as you can see `providers` is an array. - ```js title="pages/api/auth/[...nextauth].js" - import Providers from `next-auth/providers` - ... - providers: [ - Providers.Twitter({ - clientId: process.env.TWITTER_ID, - clientSecret: process.env.TWITTER_SECRET - }) - ], - ... - ``` -5. Once a provider has been setup, you can sign in at the following URL: `[origin]/api/auth/signin`. This is an unbranded auto-generated page with all the configured providers. +```js title="pages/api/auth/[...nextauth].js" +import Providers from `next-auth/providers` +... +providers: [ + Providers.Twitter({ + clientId: process.env.TWITTER_ID, + clientSecret: process.env.TWITTER_SECRET + }) +], +... +``` + +5. Once a provider has been setup, you can sign in at the following URL: `[origin]/api/auth/signin`. This is an unbranded auto-generated page with all the configured providers. Signin Screenshot +### Options + +| Name | Description | Type | Required | +| :-----------------: | :--------------------------------------------------------------: | :---------------------------: | :------: | +| id | Unique ID for the provider | `string` | Yes | +| name | Descriptive name for the provider | `string` | Yes | +| type | Type of provider, in this case `oauth` | `"oauth"` | Yes | +| version | OAuth version (e.g. '1.0', '1.0a', '2.0') | `string` | Yes | +| scope | OAuth access scopes (expects array or string) | `string` or `string[]` | Yes | +| params | Extra URL params sent when calling `accessTokenUrl` | `Object` | Yes | +| accessTokenUrl | Endpoint to retrieve an access token | `string` | Yes | +| authorizationUrl | Endpoint to request authorization from the user | `string` | Yes | +| requestTokenUrl | Endpoint to retrieve a request token | `string` | Yes | +| profileUrl | Endpoint to retrieve the user's profile | `string` | Yes | +| clientId | Client ID of the OAuth provider | `string` | Yes | +| clientSecret | Client Secret of the OAuth provider | `string` | Yes | +| profile | A callback returning an object with the user's info | `(profile, tokens) => Object` | Yes | +| protection | Additional security for OAuth login flows (defaults to `state`) | `"pkce"`,`"state"`,`"none"` | No | +| state | Same as `protection: "state"`. Being deprecated, use protection. | `boolean` | No | +| headers | Any headers that should be sent to the OAuth provider | `Object` | No | +| authorizationParams | Additional params to be sent to the authorization endpoint | `Object` | No | +| idToken | Set to `true` for services that use ID Tokens (e.g. OpenID) | `boolean` | No | +| region | Only when using BattleNet | `string` | No | +| domain | Only when using certain Providers | `string` | No | +| tenantId | Only when using Azure, Active Directory, B2C, FusionAuth | `string` | No | + +:::tip +Even if you are using a built-in provider, you can override any of these options to tweak the default configuration. + +```js title=[...nextauth].js +import Providers from "next-auth/providers" + +Providers.Auth0({ + clientId: process.env.CLIENT_ID, + clientSecret: process.env.CLIENT_SECRET, + domain: process.env.DOMAIN, + scope: "openid your_custom_scope", // We do provide a default, but this will override it if defined + profile(profile) { + return {} // Return the profile in a shape that is different from the built-in one. + }, +}) +``` + +::: + ### Using a custom provider You can use an OAuth provider that isn't built-in by using a custom object. @@ -89,7 +153,8 @@ As an example of what this looks like, this is the provider object returned for clientSecret: "" } ``` -You can replace all the options in this JSON object with the ones from your custom provider - be sure to give it a unique ID and specify the correct OAuth version - and add it to the providers option: + +Replace all the options in this JSON object with the ones from your custom provider - be sure to give it a unique ID and specify the correct OAuth version - and add it to the providers option when initializing the library: ```js title="pages/api/auth/[...nextauth].js" import Providers from `next-auth/providers` @@ -111,33 +176,24 @@ providers: [ ... ``` +### Adding a new provider +If you think your custom provider might be useful to others, we encourage you to open a PR and add it to the built-in list so others can discover it much more easily! +You only need to add two changes: -### OAuth provider options +1. Add your config: [`src/providers/{provider}.js`](https://github.com/nextauthjs/next-auth/tree/main/src/providers)
+ • make sure you use a named default export, like this: `export default function YourProvider` +2. Add provider documentation: [`www/docs/providers/{provider}.md`](https://github.com/nextauthjs/next-auth/tree/main/www/docs/providers) +3. Add it to our [provider types](https://github.com/nextauthjs/next-auth/blob/main/types/providers.d.ts) (for TS projects)
+ • you just need to add your new provider name to [this list](https://github.com/nextauthjs/next-auth/blob/main/types/providers.d.ts#L56-L97)
+ • in case you new provider accepts some custom options, you can [add them here](https://github.com/nextauthjs/next-auth/blob/main/types/providers.d.ts#L48-L53) -| Name | Description | Type | Required | -| :-----------------: | :--------------------------------------------------------------: | :-----------------------------: | :------: | -| id | Unique ID for the provider | `string` | Yes | -| name | Descriptive name for the provider | `string` | Yes | -| type | Type of provider, in this case it should be `oauth` | `oauth`, `email`, `credentials` | Yes | -| version | OAuth version (e.g. '1.0', '1.0a', '2.0') | `string` | Yes | -| accessTokenUrl | Endpoint to retrieve an access token | `string` | Yes | -| authorizationUrl | Endpoint to request authorization from the user | `string` | Yes | -| clientId | Client ID of the OAuth provider | `string` | Yes | -| clientSecret | Client Secret of the OAuth provider | `string` | No | -| scope | OAuth access scopes (expects array or string) | `string` or `string[]` | No | -| params | Additional authorization URL parameters | `object` | No | -| requestTokenUrl | Endpoint to retrieve a request token | `string` | No | -| authorizationParams | Additional params to be sent to the authorization endpoint | `object` | No | -| profileUrl | Endpoint to retrieve the user's profile | `string` | No | -| profile | A 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]`,`[pkce,state]`| No | -| state | Same as `protection: "state"`. Being deprecated, use protection. | `boolean` | No | +That's it! 🎉 Others will be able to discover this provider much more easily now! + +## Email Provider -## Sign in with Email +### How to The Email provider uses email to send "magic links" that can be used sign in, you will likely have seen them before if you have used software like Slack. @@ -164,8 +220,21 @@ See the [Email provider documentation](/providers/email) for more information on The email provider requires a database, it cannot be used without one. ::: +### Options + +| Name | Description | Type | Required | +| :---------------------: | :---------------------------------------------------------------------------------: | :------------------------------: | :------: | +| id | Unique ID for the provider | `string` | Yes | +| name | Descriptive name for the provider | `string` | Yes | +| type | Type of provider, in this case `email` | `"email"` | Yes | +| server | Path or object pointing to the email server | `string` or `Object` | Yes | +| sendVerificationRequest | Callback to execute when a verification request is sent | `(params) => Promise` | Yes | +| from | The email address from which emails are sent, default: "" | `string` | No | +| maxAge | How long until the e-mail can be used to log the user in seconds. Defaults to 1 day | `number` | No | -## Sign in with Credentials +## Credentials Provider + +### How to The Credentials provider allows you to handle signing in with arbitrary credentials, such as a username and password, two factor authentication or hardware device (e.g. YubiKey U2F / FIDO). @@ -211,26 +280,12 @@ See the [Credentials provider documentation](/providers/credentials) for more in The Credentials provider can only be used if JSON Web Tokens are enabled for sessions. Users authenticated with the Credentials provider are not persisted in the database. ::: - -export const Image = ({ children, src, alt = '' }) => ( -
- {alt} -
- ) - - -## Adding a new built-in provider - -If you think your custom provider might be useful to others, we encourage you to open a PR and add it to the built-in list so others can discover it much more easily! You only need to add two changes: -1. Add your config: [`src/providers/{provider}.js`](https://github.com/nextauthjs/next-auth/tree/main/src/providers) (Make sure you use a named default export, like `export default function YourProvider`!) -2. Add provider documentation: [`www/docs/providers/{provider}.md`](https://github.com/nextauthjs/next-auth/tree/main/www/docs/providers) - -That's it! 🎉 Others will be able to discover this provider much more easily now! +### Options -You can look at the existing built-in providers for inspiration. +| Name | Description | Type | Required | +| :---------: | :-----------------------------------------------: | :------------------------------: | :------: | +| id | Unique ID for the provider | `string` | Yes | +| name | Descriptive name for the provider | `string` | Yes | +| type | Type of provider, in this case `credentials` | `"credentials"` | Yes | +| credentials | The credentials to sign-in with | `Object` | Yes | +| authorize | Callback to execute once user is to be authorized | `(credentials) => Promise` | Yes | diff --git a/www/src/css/index.css b/www/src/css/index.css index 53bc71ac5d..62ae6d9f04 100644 --- a/www/src/css/index.css +++ b/www/src/css/index.css @@ -46,6 +46,7 @@ html[data-theme="dark"]:root { @import "buttons.css"; @import "table-of-contents.css"; @import "sidebar.css"; +@import "providers.css"; @media screen and (max-width: 360px) { html { diff --git a/www/src/css/providers.css b/www/src/css/providers.css new file mode 100644 index 0000000000..3b7cdb0383 --- /dev/null +++ b/www/src/css/providers.css @@ -0,0 +1,9 @@ +.provider-name-list { + display: flex; + flex-wrap: wrap; +} + +.provider-name-list__comma { + display: inline-flex; + margin-right: 5px; +} From b1653f5ffe6157514f7a59c7b2b4387aa67a5d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Poduszl=C3=B3?= Date: Mon, 3 May 2021 14:31:56 +0200 Subject: [PATCH 09/16] fix(ts): unset generics defaults for overriding (#1891) Co-authored-by: Lluis Agusti --- types/adapters.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/types/adapters.d.ts b/types/adapters.d.ts index af51b6cfd6..f2fc9707f0 100644 --- a/types/adapters.d.ts +++ b/types/adapters.d.ts @@ -120,9 +120,9 @@ export interface AdapterInstance { export type Adapter< C = Record, O = Record, - U = User, - P = Profile, - S = Session + U = unknown, + P = unknown, + S = unknown > = ( config?: C, options?: O From c6964a77340188aaf62337c51da12edeb043aa4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Orb=C3=A1n?= Date: Mon, 3 May 2021 21:24:19 +0200 Subject: [PATCH 10/16] fix(ts): tweak Adapter related types (#1914) Contains the following squashed commits: * fix(ts): make first adapter parameter non-optional * fix(ts): make defaulted values non-optional internally * test(ts): fix linting --- types/adapters.d.ts | 4 ++-- types/index.d.ts | 10 +++++++++- types/internals/index.d.ts | 12 ++++++------ types/tests/server.test.ts | 6 ++++-- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/types/adapters.d.ts b/types/adapters.d.ts index f2fc9707f0..96174c922f 100644 --- a/types/adapters.d.ts +++ b/types/adapters.d.ts @@ -118,13 +118,13 @@ export interface AdapterInstance { * [Create a custom adapter](https://next-auth.js.org/tutorials/creating-a-database-adapter) */ export type Adapter< - C = Record, + C = unknown, O = Record, U = unknown, P = unknown, S = unknown > = ( - config?: C, + client: C, options?: O ) => { getAdapter(appOptions: AppOptions): Promise> diff --git a/types/index.d.ts b/types/index.d.ts index 2697955353..42c52157b0 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -180,7 +180,7 @@ export interface NextAuthOptions { * * [Documentation](https://next-auth.js.org/configuration/options#theme) | [Pages documentation]("https://next-auth.js.org/configuration/pages") */ - theme?: "auto" | "dark" | "light" + theme?: Theme /** * When set to `true` then all cookies set by NextAuth.js will only be accessible from HTTPS URLs. * This option defaults to `false` on URLs that start with `http://` (e.g. http://localhost:3000) for developer convenience. @@ -215,6 +215,14 @@ export interface NextAuthOptions { cookies?: CookiesOptions } +/** + * Change the theme of the built-in pages. + * + * [Documentation](https://next-auth.js.org/configuration/options#theme) | + * [Pages](https://next-auth.js.org/configuration/pages) + */ +export type Theme = "auto" | "dark" | "light" + /** * Override any of the methods, and the rest will use the default logger. * diff --git a/types/internals/index.d.ts b/types/internals/index.d.ts index 54a88638bf..65840061bf 100644 --- a/types/internals/index.d.ts +++ b/types/internals/index.d.ts @@ -1,5 +1,5 @@ import { NextApiRequest, NextApiResponse } from "./utils" -import { NextAuthOptions } from ".." +import { LoggerInstance, NextAuthOptions, SessionOptions, Theme } from ".." import { AppProvider } from "../providers" /** Options that are the same both in internal and user provided options. */ @@ -9,12 +9,7 @@ export type NextAuthSharedOptions = | "events" | "callbacks" | "cookies" - | "secret" | "adapter" - | "theme" - | "debug" - | "logger" - | "session" export interface AppOptions extends Required> { @@ -42,6 +37,11 @@ export interface AppOptions provider?: AppProvider csrfToken?: string csrfTokenVerified?: boolean + secret: string + theme: Theme + debug: boolean + logger: LoggerInstance + session: Required } export interface NextAuthRequest extends NextApiRequest { diff --git a/types/tests/server.test.ts b/types/tests/server.test.ts index 630f9fe0de..e389bccc11 100644 --- a/types/tests/server.test.ts +++ b/types/tests/server.test.ts @@ -60,7 +60,7 @@ const exampleVerificationRequest = { expires: new Date(), } -const MyAdapter: Adapter = () => { +const MyAdapter: Adapter> = () => { return { async getAdapter(appOptions: AppOptions) { return { @@ -126,6 +126,8 @@ const MyAdapter: Adapter = () => { } } +const client = {} // Create a fake db client + const allConfig: NextAuthTypes.NextAuthOptions = { providers: [ Providers.Twitter({ @@ -192,7 +194,7 @@ const allConfig: NextAuthTypes.NextAuthOptions = { return undefined }, }, - adapter: MyAdapter(), + adapter: MyAdapter(client), useSecureCookies: true, cookies: { sessionToken: { From 057d548cdfa978bec565ce1c959be479750d7712 Mon Sep 17 00:00:00 2001 From: Anubisoft <1471887+anubisoft@users.noreply.github.com> Date: Mon, 3 May 2021 13:43:38 -0700 Subject: [PATCH 11/16] fix(page): don't pass params to custom signout page (#1912) * For the custom signout page addressed two issues with the query params being added to the signout url. A conditional check on the error value is now made before adding it as a query param. Also added a conditional check on the callbackUrl and if present that then gets appended as a query param to the signout api call. * Changed fix for bug #192 to have no querystring params in the custom signout page url. Co-authored-by: anubisoft Co-authored-by: Lluis Agusti --- src/server/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/server/index.js b/src/server/index.js index be963b0df0..4e9ca6c7f3 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -158,9 +158,8 @@ async function NextAuthHandler (req, res, userOptions) { return render.signin() case 'signout': - if (pages.signOut) { - return res.redirect(`${pages.signOut}${pages.signOut.includes('?') ? '&' : '?'}error=${error}`) - } + if (pages.signOut) return res.redirect(pages.signOut) + return render.signout() case 'callback': if (provider) { From f94e155b68afde73da2628f9a6abcbf50393f156 Mon Sep 17 00:00:00 2001 From: Ernie Miranda Date: Tue, 4 May 2021 13:34:06 -0400 Subject: [PATCH 12/16] docs(www): fix typo (#1922) --- www/docs/configuration/options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/docs/configuration/options.md b/www/docs/configuration/options.md index 2801b403ea..28c3a2e126 100644 --- a/www/docs/configuration/options.md +++ b/www/docs/configuration/options.md @@ -400,7 +400,7 @@ Properties on any custom `cookies` that are specified override this option. ::: :::warning -Setting this option to _false_ in production is a security risk and may allow sessions to hijacked if used in production. It is intended to support development and testing. Using this option is not recommended. +Setting this option to _false_ in production is a security risk and may allow sessions to be hijacked if used in production. It is intended to support development and testing. Using this option is not recommended. ::: --- From fa345b1da10d4f018b4ae4efa402666d0642f760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathis=20M=C3=B8ller?= Date: Wed, 5 May 2021 15:17:22 +0200 Subject: [PATCH 13/16] docs(provider): Update IdentityServer 4 demo configuration (#1932) --- www/docs/providers/identity-server4.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/www/docs/providers/identity-server4.md b/www/docs/providers/identity-server4.md index 577f9d9916..13126e6c89 100644 --- a/www/docs/providers/identity-server4.md +++ b/www/docs/providers/identity-server4.md @@ -7,7 +7,6 @@ title: IdentityServer4 https://identityserver4.readthedocs.io/en/latest/ - ## Example ```js @@ -15,8 +14,8 @@ import Providers from `next-auth/providers` ... providers: [ Providers.IdentityServer4({ - id: "identity-server4", - name: "IdentityServer4", + id: "identity-server4", + name: "IdentityServer4", scope: "openid profile email api offline_access", // Allowed Scopes domain: process.env.IdentityServer4_Domain, clientId: process.env.IdentityServer4_CLIENT_ID, @@ -33,18 +32,20 @@ The configuration below is for the demo server at https://demo.identityserver.io If you want to try it out, you can copy and paste the configuration below. You can sign in to the demo service with either bob/bob or alice/alice. - + ```js import Providers from `next-auth/providers` ... providers: [ Providers.IdentityServer4({ - id: "demo-identity-server", - name: "Demo IdentityServer4", - scope: "openid profile email api offline_access", + id: "demo-identity-server", + name: "Demo IdentityServer4", + scope: "openid profile email api offline_access", domain: "demo.identityserver.io", - clientId: "server.code", - clientSecret: "secret" + clientId: "interactive.confidential", + clientSecret: "secret", + protection: "pkce" }) } ... +``` From 4296137271d3181f24443b201ae60a4f8ad7e9e7 Mon Sep 17 00:00:00 2001 From: Zack Sheppard Date: Wed, 5 May 2021 15:45:14 +0100 Subject: [PATCH 14/16] Responding to code review comments --- types/index.d.ts | 52 ++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 42c52157b0..283e2f6aa2 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -360,59 +360,51 @@ export type EventCallback = ( * 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. */ -export interface SignInEventMessage { - user: TUser - account: Record +export interface SignInEventMessage { + user: User + account: Account isNewUser?: boolean } -export interface LinkAccountEventMessage { - user: TUser +export interface LinkAccountEventMessage { + user: User providerAccount: Record } /** * The various event callbacks you can register for from next-auth */ -export interface EventCallbacks< - TSignOutMessage = unknown, - TSessionMessage = unknown -> { - signIn: EventCallback> - signOut: EventCallback +export interface CommonEventCallbacks { + signIn: EventCallback createUser: EventCallback updateUser: EventCallback - linkAccount: EventCallback> - session: EventCallback - error: EventCallback + linkAccount: EventCallback + error: EventCallback } - /** * The event callbacks will take this form if you are using JWTs: * signOut will receive the JWT and session will receive the session and JWT. */ -export type JWTEventCallbacks = EventCallbacks< - JWT & Record, - { - session: Session & Record +export interface JWTEventCallbacks extends CommonEventCallbacks { + signOut: EventCallback + session: EventCallback<{ + session: Session jwt: JWT - } -> - + }> +} /** * The event callbacks will take this form if you are using Sessions * and not using JWTs: - * signOut will receive the underlying db adapter's session object, and session + * signOut will receive the underlying DB adapter's session object, and session * will receive the NextAuth client session with extra data. */ -export type SessionEventCallbacks = EventCallbacks< - Session | null, - { - session: Session & Record - } -> +export interface SessionEventCallbacks extends CommonEventCallbacks { + signOut: EventCallback + session: EventCallback<{ session: Session }> +} +export type EventCallbacks = JWTEventCallbacks | SessionEventCallbacks -export type EventType = keyof EventCallbacks +export type EventType = keyof EventCallbacks /** [Documentation](https://next-auth.js.org/configuration/pages) */ export interface PagesOptions { From c9da56cb74485e0886331ef9448c3bbf65a934a5 Mon Sep 17 00:00:00 2001 From: Zack Sheppard Date: Wed, 5 May 2021 22:18:28 +0100 Subject: [PATCH 15/16] Fix tests --- types/tests/server.test.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/types/tests/server.test.ts b/types/tests/server.test.ts index e389bccc11..b2f38bf821 100644 --- a/types/tests/server.test.ts +++ b/types/tests/server.test.ts @@ -168,9 +168,7 @@ const allConfig: NextAuthTypes.NextAuthOptions = { }, }, events: { - async signIn( - message: NextAuthTypes.SignInEventMessage - ) { + async signIn(message: NextAuthTypes.SignInEventMessage) { return undefined }, async signOut(message: NextAuthTypes.Session | null) { @@ -182,9 +180,7 @@ const allConfig: NextAuthTypes.NextAuthOptions = { async updateUser(message: NextAuthTypes.User) { return undefined }, - async linkAccount( - message: NextAuthTypes.LinkAccountEventMessage - ) { + async linkAccount(message: NextAuthTypes.LinkAccountEventMessage) { return undefined }, async session(message: NextAuthTypes.Session) { From 023d44701aea6adda85543a92ff40386a07e98ab Mon Sep 17 00:00:00 2001 From: Zack Sheppard Date: Thu, 6 May 2021 10:15:48 +0100 Subject: [PATCH 16/16] Fix lint error --- types/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index 283e2f6aa2..1a8a42e8d2 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -379,7 +379,7 @@ export interface CommonEventCallbacks { createUser: EventCallback updateUser: EventCallback linkAccount: EventCallback - error: EventCallback + error: EventCallback } /** * The event callbacks will take this form if you are using JWTs: