nextauthjs/next-auth · error

unsupported client authentication method

Error message

unsupported client authentication method

What it means

Auth.js selects the client authentication method for the token endpoint based on token_endpoint_auth_method; only client_secret_basic, client_secret_post, and none are supported. Any other value reaches the switch's default branch and throws Error('unsupported client authentication method'). The valid values mirror openid-client's supported authentication methods.

Source

Thrown at packages/core/src/lib/actions/callback/oauth/callback.ts:125

    case "client_secret_post":
      clientAuth = o.ClientSecretPost(provider.clientSecret!)
      break
    case "client_secret_jwt":
      clientAuth = o.ClientSecretJwt(provider.clientSecret!)
      break
    case "private_key_jwt":
      clientAuth = o.PrivateKeyJwt(provider.token!.clientPrivateKey!, {
        // TODO: review in the next breaking change
        [o.modifyAssertion](_header, payload) {
          payload.aud = [as.issuer, as.token_endpoint!]
        },
      })
      break
    case "none":
      clientAuth = o.None()
      break
    default:
      throw new Error("unsupported client authentication method")
  }

  const resCookies: Cookie[] = []

  const state = await checks.state.use(cookies, resCookies, options)

  let codeGrantParams: URLSearchParams
  try {
    codeGrantParams = o.validateAuthResponse(
      as,
      client,
      new URLSearchParams(params),
      provider.checks.includes("state") ? state : o.skipStateCheck
    )
  } catch (err) {
    if (err instanceof o.AuthorizationResponseError) {
      const cause = {
        providerId: provider.id,

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Set the provider's token_endpoint_auth_method to "client_secret_basic", "client_secret_post", or "none" (whichever the IdP accepts)
  2. Check the IdP's discovery document for which methods its token endpoint supports and pick a supported one
  3. If the IdP only supports private_key_jwt/mTLS, use a middleware or a different client that implements it, or ask the IdP to enable client_secret_* auth
  4. Fix casing/typos in custom provider definitions

Example fix

// before
const provider = {
  id: "acme", type: "oidc", issuer: "https://sso.acme.com",
  token_endpoint_auth_method: "private_key_jwt", clientId, clientSecret
}
// after
const provider = {
  id: "acme", type: "oidc", issuer: "https://sso.acme.com",
  token_endpoint_auth_method: "client_secret_post", clientId, clientSecret
}
Defensive patterns

Strategy: validation

Validate before calling

const allowed = ["client_secret_basic", "client_secret_post", "none"]
if (provider.token_endpoint_auth_method &&
    !allowed.includes(provider.token_endpoint_auth_method)) {
  throw new Error(`Unsupported auth method: ${provider.token_endpoint_auth_method}`)
}

Type guard

function isSupportedAuthMethod(m: string): m is "client_secret_basic" | "client_secret_post" | "none" {
  return ["client_secret_basic","client_secret_post","none"].includes(m)
}

Try / catch

try {
  await signIn(providerId)
} catch (e) {
  if ((e as Error).message === "unsupported client authentication method") {
    // set token_endpoint_auth_method to a supported value
  }
}

Prevention

When it happens

Trigger: A provider config (or discovery document) declares token_endpoint_auth_method with a value such as private_key_jwt, tls_client_auth, or an arbitrary string that Auth.js does not implement; a typo like "client_secret_Post" in a custom provider.

Common situations: Providers requiring advanced auth (mTLS, private_key_jwt — e.g. some enterprise/healthcare IdPs) being wired into Auth.js which lacks support; copy-pasting token_endpoint_auth_method from the IdP's docs verbatim; hand-written provider objects with invalid enum values.

Understand the failure class

Related errors


AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/7574bb6fbc36fff9. Report an issue: GitHub.