Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/adapters/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ User creation in the database is automatic, and happens when the user is logging
The Account model is for information about OAuth accounts associated with a User. It will usually contain `access_token`, `id_token` and other OAuth specific data. [`TokenSet`](https://github.com/panva/node-openid-client/blob/main/docs/README.md#new-tokensetinput) from `openid-client` might give you an idea of all the fields.

:::note
In case of an OAuth 1.0 provider (like Twitter), you will have to look for `oauth_token` and `oauth_token_secret` string fields. GitHub also has an extra `refresh_token_expires_in` integer field. You have to make sure that your database schema includes these fields.
In case of an OAuth 1.0 provider (like Twitter), you will have to look for `oauth_token` and `oauth_token_secret` string fields. GitHub also has an extra `refresh_token_expires_in` integer field. You have to make sure that your database schema includes these fields or configure the [`allowedAccountTokens`](/configuration/options#allowedaccounttokens) option.
:::

A single User can have multiple Accounts, but each Account can only have one User.
Expand Down
29 changes: 28 additions & 1 deletion docs/docs/configuration/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ Using [System Environment Variables](https://vercel.com/docs/concepts/projects/e

Used to encrypt the NextAuth.js JWT, and to hash [email verification tokens](/adapters/models#verification-token). This is the default value for the `secret` option in [NextAuth](/configuration/options#secret) and [Middleware](/configuration/nextjs#secret).


### NEXTAUTH_URL_INTERNAL

If provided, server-side calls will use this instead of `NEXTAUTH_URL`. Useful in environments when the server doesn't have access to the canonical URL of your site. Defaults to `NEXTAUTH_URL`.
Expand Down Expand Up @@ -308,6 +307,34 @@ By default NextAuth.js does not include an adapter any longer. If you would like

---

### allowedAccountTokens

- **Default value**: All tokens are allowed
- **Required**: _No_

#### Description

By default NextAuth.js stores all information about an OAuth account gathered by the provider on the [Account Model](/adapters/models#account).
These tokens can include fields that are not defined on the database schema. With this option the tokens can be filtered before being stored on the Account.

_For example:_

```js
allowedAccountTokens: [
"refresh_token",
"access_token",
"expires_at",
"token_type",
"scope",
"id_token",
"session_state",
],
```

ensures only the fields that are supported by the [default Prisma schema](/adapters/prisma) are stored.

---

### debug

- **Default value**: `false`
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/providers/azure-ad-b2c.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Azure AD B2C returns the following fields on `Account`:
- `id_token_expires_in` (number)
- `profile_info` (string).

See their [docs](https://docs.microsoft.com/en-us/azure/active-directory-b2c/access-tokens). Remember to add these fields to your database schema, in case if you are using an [Adapter](/adapters/overview).
See their [docs](https://docs.microsoft.com/en-us/azure/active-directory-b2c/access-tokens). Remember to add these fields to your database schema, in case if you are using an [Adapter](/adapters/overview) or configure the [`allowedAccountTokens`](/configuration/options#allowedaccounttokens) option.
:::

## Documentation
Expand Down
24 changes: 21 additions & 3 deletions packages/next-auth/src/core/lib/oauth/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default async function oAuthCallback(params: {
cookies: RequestInternal["cookies"]
}): Promise<GetProfileResult & { cookies?: OutgoingResponse["cookies"] }> {
const { options, query, body, method, cookies } = params
const { logger, provider } = options
const { logger, provider, allowedAccountTokens } = options

const errorMessage = body?.error ?? query?.error
if (errorMessage) {
Expand Down Expand Up @@ -57,7 +57,13 @@ export default async function oAuthCallback(params: {
profile = JSON.parse(profile)
}

return await getProfile({ profile, tokens, provider, logger })
return await getProfile({
profile,
tokens,
provider,
allowedAccountTokens,
logger,
})
} catch (error) {
logger.error("OAUTH_V1_GET_ACCESS_TOKEN_ERROR", error as Error)
throw error
Expand Down Expand Up @@ -142,6 +148,7 @@ export default async function oAuthCallback(params: {
profile,
provider,
tokens,
allowedAccountTokens,
logger,
})
return { ...profileResult, cookies: resCookies }
Expand All @@ -158,6 +165,7 @@ export interface GetProfileParams {
profile: Profile
tokens: TokenSet
provider: OAuthConfig<any>
allowedAccountTokens?: string[]
logger: LoggerInstance
}

Expand All @@ -173,21 +181,31 @@ async function getProfile({
profile: OAuthProfile,
tokens,
provider,
allowedAccountTokens,
logger,
}: GetProfileParams): Promise<GetProfileResult> {
try {
logger.debug("PROFILE_DATA", { OAuthProfile })
// @ts-expect-error
const profile = await provider.profile(OAuthProfile, tokens)
profile.email = profile.email?.toLowerCase()

let accountTokens = { ...tokens }
if (allowedAccountTokens) {
accountTokens = Object.fromEntries(
Object.entries(accountTokens).filter(([key]) =>
allowedAccountTokens.includes(key)
)
)
}
// Return profile, raw profile and auth provider details
return {
profile,
account: {
provider: provider.id,
type: provider.type,
providerAccountId: profile.id.toString(),
...tokens,
...accountTokens,
},
OAuthProfile,
}
Expand Down
10 changes: 10 additions & 0 deletions packages/next-auth/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ export interface NextAuthOptions {
* [Adapters Overview](https://next-auth.js.org/adapters/overview)
*/
adapter?: Adapter
/**
* Filter the tokens from the provider before storing it in the Account.
*
* * **Default value**: All tokens are allowed
* * **Required**: *No*
*
* [Documentation](https://next-auth.js.org/configuration/options#allowedaccounttokens) |
*/
allowedAccountTokens?: string[]
/**
* Set debug to true to enable debug messages for authentication and database operations.
* * **Default value**: `false`
Expand Down Expand Up @@ -536,6 +545,7 @@ export interface InternalOptions<T extends ProviderType = any> {
jwt: JWTOptions
events: Partial<EventCallbacks>
adapter?: Adapter
allowedAccountTokens?: string[]
callbacks: CallbacksOptions
cookies: CookiesOptions
callbackUrl: string
Expand Down