Skip to main content
Version: v4

OAuth Provider

Authentication Providers in NextAuth.js are OAuth definitions which allow your users to sign in with their favorite preexisting logins. You can use any of our many predefined providers, or write your own custom OAuth configuration.


NextAuth.js is designed to work with any OAuth service, it supports OAuth 1.0, 1.0A, 2.0 and OpenID Connect and has built-in support for most popular sign-in services.

Without going into too much detail, the OAuth flow generally has 6 parts:

  1. The application requests authorization to access service resources from the user
  2. If the user authorized the request, the application receives an authorization grant
  3. The application requests an access token from the authorization server (API) by presenting authentication of its own identity, and the authorization grant
  4. If the application identity is authenticated and the authorization grant is valid, the authorization server (API) issues an access token to the application. Authorization is complete.
  5. The application requests the resource from the resource server (API) and presents the access token for authentication
  6. If the access token is valid, the resource server (API) serves the resource to the application
OAuth Flow Diagram

For more details, check out Aaron Parecki's blog post OAuth2 Simplified or Postman's blog post OAuth 2.0: Implicit Flow is Dead, Try PKCE Instead.

How to#

  1. Register your application at the developer portal of your provider. There are usually links to the portals included in the aforementioned documentation pages for each supported provider with details on how to register your application.

  2. The redirect URI (sometimes called Callback URL) should follow this format:


[provider] refers to the id of your provider (see options). For example, Twitter on localhost this would be:


Using Google in our example application would look like this:
  1. Create a .env file at the root of your project and add the client ID and client secret. For Twitter this would be:
  1. 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.
import TwitterProvider from "next-auth/providers/"...providers: [  TwitterProvider({    clientId: process.env.TWITTER_ID,    clientSecret: process.env.TWITTER_SECRET  })],...
  1. 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


interface OAuthConfig {  /**   * OpenID Connect (OIDC) compliant providers can configure   * this instead of `authorize`/`token`/`userinfo` options   * without further configuration needed in most cases.   * You can still use the `authorize`/`token`/`userinfo`   * options for advanced control.   *   * [Authorization Server Metadata](   */  wellKnown?: string  /**   * The login process will be initiated by sending the user to this URL.   *   * [Authorization endpoint](   */  authorization: EndpointHandler<AuthorizationParameters>  /**   * Endpoint that returns OAuth 2/OIDC tokens and information about them.   * This includes `access_token`, `id_token`, `refresh_token`, etc.   *   * [Token endpoint](   */  token: EndpointHandler<    UrlParams,    {      /**       * Parameters extracted from the request to the `/api/auth/callback/:providerId` endpoint.       * Contains params like `state`.       */      params: CallbackParamsType      /**       * When using this custom flow, make sure to do all the necessary security checks.       * Thist object contains parameters you have to match against the request to make sure it is valid.       */      checks: OAuthChecks    },    { tokens: TokenSet }  >  /**   * When using an OAuth 2 provider, the user information must be requested   * through an additional request from the userinfo endpoint.   *   * [Userinfo endpoint](   */  userinfo?: EndpointHandler<UrlParams, { tokens: TokenSet }, Profile>  type: "oauth"  /**   * Used in URLs to refer to a certain provider.   * @example /api/auth/callback/twitter // where the `id` is "twitter"   */  id: string  version: string  accessTokenUrl: string  requestTokenUrl?: string  profile(profile: P, tokens: TokenSet): Awaitable<User & { id: string }>  checks?: ChecksType | ChecksType[]  clientId: string  clientSecret:    | string    | Record<"appleId" | "teamId" | "privateKey" | "keyId", string>  /**   * If set to `true`, the user information will be extracted   * from the `id_token` claims, instead of   * making a request to the `userinfo` endpoint.   *   * `id_token` is usually present in OpenID Connect (OIDC) compliant providers.   *   * [`id_token` explanation](   */  idToken?: boolean  region?: string  issuer?: string  tenantId?: string}

Even if you are using a built-in provider, you can override any of these options to tweak the default configuration.

import Auth0Provider from "next-auth/providers/auth0"
Auth0Provider({  clientId: process.env.CLIENT_ID,  clientSecret: process.env.CLIENT_SECRET,  issuer: process.env.ISSUER,  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.

As an example of what this looks like, this is the provider object returned for the Google provider:

{  id: "google",  name: "Google",  type: "oauth",  wellKnown: "",  authorization: { params: { scope: "openid email profile" } },  idToken: true,  checks: ["pkce", "state"],  profile(profile) {    return {      id: profile.sub,      name:,      email:,      image: profile.picture,    }  },}

As you can see, if your provider supports OpenID Connect and the /.well-known/openid-configuration endpoint contains support for the grant_type: authorization_code, you only need to pass the URL to that configuration file and define some basic fields like name and type.

Otherwise, you can pass a more full set of URLs for each OAuth2.0 flow step, for example:

{  id: "kakao",  name: "Kakao",  type: "oauth",  authorization: "",  token: "",  userinfo: "",  profile(profile) {    return {      id:,      name: profile.kakao_account?.profile.nickname,      email: profile.kakao_account?.email,      image: profile.kakao_account?.profile.profile_image_url,    }  },}

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 required URLs, and finally add it to the providers array when initializing the library:

import TwitterProvider from "next-auth/providers/twitter"...providers: [  TwitterProvider({    clientId: process.env.TWITTER_ID,    clientSecret: process.env.TWITTER_SECRET,  }),  {    id: 'customProvider',    name: 'CustomProvider',    type: 'oauth',    scope: ''  // Make sure to request the users email address    ...  }]...

Built-in providers#

NextAuth.js comes with a set of built-in providers. You can find them here. Each built-in provider has its own documentation page:

Override default options#

For built-in providers, in most cases you will only need to specify the clientId and clientSecret. If you need to override any of the defaults, add your own options.

For example, the profile callback will return id, name, email and picture by default, but you might need more information from the provider. After setting the correct scopes, you can then do something like this:

export default function NextAuth({  ...,  providers: [    GoogleProvider({      clientId: process.env.GOOGLE_CLIENT_ID,      clientSecret: process.env.GOOGLE_CLIENT_SECRET,      authorization: { params: {scope: "your custom scopes"} },      profile(profile) {        return {          // Return all the profile information you need        }      }    })  ]})

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:

  1. Add your config: src/providers/{provider}.ts
    โ€ข make sure you use a named default export, like this: export default function YourProvider
  2. Add provider documentation: /docs/providers/{provider}.md

That's it! ๐ŸŽ‰ Others will be able to discover and use this provider much more easily now!