mrkeyoor.com_
Sat 08 Aug 20:59 UTC
npmSecurityupdated 08 Aug 2026

@auth/core

@auth/core is the framework-neutral engine under Auth.js integrations. Give its Auth function a standard Web Request plus providers and security configuration, and it returns a standard Response for sign-in, OAuth callbacks, sessions, sign-out, CSRF handling, and built-in pages. It supports OAuth and OIDC providers, encrypted stateless JWT sessions, database sessions through adapters, email links, credentials, and experimental WebAuthn. This is authentication plumbing and protocol handling, not user authorization, account administration, password storage, or a drop-in UI product.

Verdict

Use @auth/core directly for framework integration work or when its database-free encrypted sessions are the point. For ordinary new applications, follow the project's own recommendation and evaluate Better Auth first; official Auth.js framework packages are also safer than wiring the experimental core by hand.

API stability2/5The package is still on 0.41.3, and its source-level module documentation places an Experimental warning above the main entry point. The standard Request-to-Response shape is clean, but provider configuration, environment defaults, adapter contracts, callbacks, and experimental WebAuthn remain a wide surface. The repository's move under Better Auth adds strategic uncertainty even while current APIs continue to work.
Docs4/5authjs.dev has generated references for the core config, callbacks, errors, JWT helpers, adapters, and each provider, plus guides for deployment and security. Source comments clearly document mandatory secrets, trusted hosts, session defaults, and Credentials limitations. Some examples target framework integrations and /api/auth rather than direct core's /auth default, so direct adopters must reconcile context carefully.
Maintenance4/5Version 0.41.3 was published on July 20, 2026, and the monorepo was pushed on July 22, 2026. The code actively tracks jose, oauth4webapi, Nodemailer, and WebAuthn dependencies. GitHub reports 592 open issues and pull requests across the large NextAuth and Auth.js monorepo, and the Better Auth transition means active maintenance should not be mistaken for an independent long-term roadmap.
Ecosystem5/5npm recorded 4,051,196 downloads for the measured week, and the repository has 28,317 stars. Auth.js offers many built-in OAuth and OIDC providers plus adapter packages for major SQL, document, and hosted databases, while standard Web APIs make runtime integrations possible. That ecosystem is the package's strongest asset, though new-project momentum is now explicitly being directed toward Better Auth.

Use it if

  • You are writing an Auth.js integration for a framework or runtime built around standard Request and Response APIs
  • You specifically need encrypted stateless sessions without a database, the feature the project README names as Auth.js's notable reason for new adoption
  • You want many preconfigured OAuth and OIDC providers while keeping users and sessions in your own infrastructure
  • You need one core that can switch between JWT sessions and a database adapter without outsourcing identity data to a hosted vendor
Skip it if

Setup reality

Direct use is more involved than importing Auth. Route both GET and POST requests under the default /auth base path, or set basePath explicitly, and register the resulting callback URL with every OAuth provider. Every call needs a secret and a trusted host. The core Auth function does not read process.env for you; either pass provider credentials, secret, basePath, and trustHost directly or call the exported setEnvDefaults(process.env, config) before handling requests. That helper mutates the config and recognizes AUTH_SECRET, AUTH_URL, AUTH_TRUST_HOST, and AUTH_<PROVIDER>_ID or _SECRET. Only trust forwarded host headers when your proxy sanitizes them. With no adapter, sessions default to encrypted JWT cookies; adding an adapter changes the default to database sessions, which also means installing an adapter package, applying its schema and migrations, and supplying every method required by the selected features. Credentials input is unknown data and must be validated before password checks; the provider only works with JWT sessions. Email links require an adapter plus the optional nodemailer peer and SMTP configuration. WebAuthn requires both SimpleWebAuthn peers, adapter methods, and experimental.enableWebAuthn. HTTPS controls secure-cookie defaults, custom cookie settings can weaken those defaults, and callbacks decide what token fields reach the browser. Secret rotation accepts an array with the newest secret first. Test complete redirect, CSRF, proxy, cookie, account-linking, and failure flows before production, not only the happy OAuth callback.

Patterns

Bridge a Web Request to Auth.jshandle-auth-request

import { Auth, type AuthConfig } from '@auth/core';
import GitHub from '@auth/core/providers/github';

const config = {
  providers: [
    GitHub({
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
    }),
  ],
  secret: process.env.AUTH_SECRET!,
  trustHost: true,
} satisfies AuthConfig;

export function handleAuth(request: Request) {
  return Auth(request, config);
}

Forward both GET and POST requests under /auth/*; trustHost is safe only when your server or proxy validates the Host headers.

Apply Auth.js environment conventionsload-auth-environment

import { Auth, setEnvDefaults, type AuthConfig } from '@auth/core';
import GitHub from '@auth/core/providers/github';

const config: AuthConfig = { providers: [GitHub] };
setEnvDefaults(process.env, config);

export const handleAuth = (request: Request) => Auth(request, config);

Set AUTH_SECRET and AUTH_GITHUB_ID or AUTH_GITHUB_SECRET first; setEnvDefaults mutates config and direct Auth calls do not invoke it automatically.

Offer more than one OAuth providerconfigure-multiple-providers

import GitHub from '@auth/core/providers/github';
import Google from '@auth/core/providers/google';

const config = {
  providers: [
    GitHub({ clientId: githubId, clientSecret: githubSecret }),
    Google({ clientId: googleId, clientSecret: googleSecret }),
  ],
  secret,
  trustHost: true,
};

Each provider needs its own registered callback, such as /auth/callback/github and /auth/callback/google with the core default base path.

Point GitHub login at an Enterprise serveruse-github-enterprise

GitHub({
  clientId: process.env.GHE_CLIENT_ID!,
  clientSecret: process.env.GHE_CLIENT_SECRET!,
  enterprise: {
    baseUrl: 'https://github.company.example',
  },
})

The provider derives both OAuth and /api/v3 endpoints from baseUrl; register the callback on that Enterprise instance.

Allow only a verified company domainrestrict-sign-in

const config = {
  // providers, secret, trustHost...
  callbacks: {
    async signIn({ profile }) {
      const email = profile?.email;
      return typeof email === 'string' && email.endsWith('@company.example');
    },
  },
};

A domain suffix is authorization policy, not proof by itself; also require the provider's verified-email signal when its profile exposes one.

Copy a server token claim into the sessionexpose-jwt-claim

const config = {
  session: { strategy: 'jwt' as const },
  callbacks: {
    async jwt({ token, user }) {
      if (user) token.userId = user.id;
      return token;
    },
    async session({ session, token }) {
      session.user.id = token.userId as string;
      return session;
    },
  },
};

The session callback controls browser-visible data; do not copy provider access tokens or secrets unless the client truly needs them.

Persist users and sessions with a Prisma adapteruse-database-sessions

import { PrismaAdapter } from '@auth/prisma-adapter';
import { prisma } from './db.js';

const config = {
  providers,
  adapter: PrismaAdapter(prisma),
  session: { strategy: 'database' as const },
  secret,
  trustHost: true,
};

Install @auth/prisma-adapter separately and apply the Auth.js models and migrations; adding an adapter defaults sessions to database storage.

Validate a credentials sign-inauthorize-credentials

import Credentials from '@auth/core/providers/credentials';

Credentials({
  credentials: {
    email: { label: 'Email', type: 'email' },
    password: { label: 'Password', type: 'password' },
  },
  async authorize(credentials) {
    if (typeof credentials.email !== 'string') return null;
    if (typeof credentials.password !== 'string') return null;
    return verifyPassword(credentials.email, credentials.password);
  },
})

The provider performs no validation or password security for you and only supports JWT sessions; add rate limits and generic failure messages.

Configure passwordless email linkssend-email-link

import Nodemailer from '@auth/core/providers/nodemailer';

const config = {
  adapter,
  providers: [
    Nodemailer({
      server: process.env.EMAIL_SERVER!,
      from: 'Sign in <login@example.com>',
    }),
  ],
  secret,
  trustHost: true,
};

Install a compatible nodemailer peer and configure an adapter; verification tokens require database methods even if other sessions use JWTs.

Rotate secrets without dropping sessionsrotate-auth-secret

const config = {
  providers,
  secret: [
    process.env.AUTH_SECRET_NEW!,
    process.env.AUTH_SECRET_OLD!,
  ],
  trustHost: true,
};

Put the newest secret first for new encryption; old entries remain only long enough to decrypt sessions created before rotation.

Replace the built-in sign-in and error pagesset-custom-pages

const config = {
  providers,
  secret,
  trustHost: true,
  basePath: '/auth',
  pages: {
    signIn: '/login',
    error: '/auth-error',
    verifyRequest: '/check-your-email',
  },
};

Custom pages are your routes and must not redirect back into protected auth checks, especially the error page.

Send auth errors to application loggingcapture-auth-logs

const config = {
  providers,
  secret,
  trustHost: true,
  logger: {
    error(error: Error) { appLogger.error({ error }, 'auth error'); },
    warn(code) { appLogger.warn({ code }, 'auth warning'); },
    debug(message, metadata) { appLogger.debug({ metadata }, message); },
  },
};

Providing a custom logger makes the debug flag irrelevant; redact tokens, cookies, credentials, and provider responses before shipping metadata.

Alternatives

PackageRegistryPick it when
better-authnpmUse it for a new application unless Auth.js's encrypted stateless session model fills a feature gap.
passportnpmUse it in established Express or Connect middleware stacks that want strategy-based authentication and will own sessions and routes.
supertokens-nodenpmUse it when you want managed recipes for passwords, social login, sessions, account recovery, and optional hosted infrastructure.