All posts

Better Auth 1.6

OpenTelemetry instrumentation, non-blocking scrypt, passkey pre-auth registration, SAML hardening, a new release workflow, and more.

Taesu Kim·Apr 7, 2026

Better Auth 1.6

We’re excited to announce the release of Better Auth 1.6 🎉

Better Auth 1.6 is a transitional release that helps us move toward a more structured workflow.

Rather than packing in a large number of new features, this release focuses on laying groundwork for a more solid project. That said, it still includes new features, performance improvements, and a number of meaningful fixes.


Highlights

新增

OpenTelemetry 仪表化

Better Auth 现在会发出 OpenTelemetry spans 用于分布式追踪。这能让你直观地看到每个认证 API 调用,包括端点执行、钩子生命周期和数据库操作。

instrumentation.ts
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { SimpleSpanProcessor, ConsoleSpanExporter } from "@opentelemetry/sdk-trace-base";

const provider = new NodeTracerProvider({
  spanProcessors: [new SimpleSpanProcessor(new ConsoleSpanExporter())],
});
provider.register();

Once a TracerProvider is registered, Better Auth automatically emits spans through the better-auth emitter. No additional configuration is needed in your authentication setup.

Supported spans include:

  • Endpoint spans: GET /get-session, POST /sign-in/email, and more.
  • Database spans: db create user, db findOne session, and more.
  • Hook spans: before/after hooks, middleware, onRequest/onResponse

Each span carries attributes such as http.route, db.operation.name, db.collection.name, and better_auth.operation_id for filtering and grouping in observability tools.

This feature is experimental, and the span structure may change in future releases. For more information, see the instrumentation docs.


新增

Passkey 预认证注册

The Passkey plugin now supports registering a Passkey before a user has a session. This makes Passkey-first signup flows possible, where Passkey itself is the initial authentication method.

auth.ts
import { betterAuth } from "better-auth";
import { passkey } from "@better-auth/passkey";

export const auth = betterAuth({
  plugins: [
    passkey({
      registration: {
        requireSession: false, 
        resolveUser: async ({ ctx, context }) => {
          // Validate the context (for example, a signed token), then create or load the user.
          return { id: "user-id", name: "user@example.com" };
        },
      },
    }),
  ],
});

The plugin also adds support for WebAuthn extensions during registration and authentication, allowing you to pass server-defined extensions such as credProps.

For more information, see the Passkey docs.


新增

不区分大小写的查询

Database queries now support case-insensitive string comparisons across all adapters (Drizzle, Prisma, Kysely, MongoDB, in-memory).

This is an internal API for plugin authors and is used by the core when needed. Queries can specify mode: "insensitive" in a separate where clause:

adapter.findOne({
  model: "user",
  where: [{
    field: "email",
    value: "user@example.com",
    mode: "insensitive", 
  }],
});

Under the hood, each adapter picks the most efficient case-insensitive strategy supported by its database.


破坏性变更

使 Fresh Age 与会话创建时间对齐

The freshAge check now uses createdAt instead of updatedAt. Previously, any session refresh would reset the freshness window, which meant a session could remain “fresh” indefinitely through regular access. Now freshness is tied to the session creation time, so sensitive actions like password changes or payment confirmation require a recent sign-in.

For more information, see the session freshness docs.


破坏性变更

默认启用 SAML 流程中的 InResponseTo 验证

SAML InResponseTo validation is now enabled by default in SP-initiated flows to prevent replay attacks, where a captured assertion can be reused. IDP-initiated single sign-on is unaffected. If needed, you can opt out explicitly:

sso({
  saml: {
    enableInResponseToValidation: false, 
  },
});

For more information, see the SSO docs.


性能

更快速、更轻量

Two changes affect every Better Auth user:

  1. 非阻塞式 scrypt

    Password hashing now uses the native node:crypto scrypt implementation, running on libuv’s thread pool instead of blocking the main thread. In runtimes that don’t support node:crypto, it falls back to a pure JavaScript implementation. Existing password hashes remain fully compatible.

  2. 减小包体积

    The published package is now significantly smaller, which means faster installs and less disk usage.

    包名v1.5.6v1.6.0减少
    better-auth4,236 KB2,265 KB46%

重要变更

破坏性变更

变更描述
使 Fresh Age 与会话创建时间对齐freshAge 现在使用 createdAt 而非 updatedAt。会话可能需要更频繁地重新认证以执行敏感操作。详情
默认启用 SAML 流程中的 InResponseTo 验证SAML InResponseTo 验证现已默认开启。设置 enableInResponseToValidation: false 可禁用。详情

行为变更

变更描述
SCIM 端点授权强制SCIM 管理端点现在需要适当的认证。Passkey 所有权标准化以防止跨用户访问。
无状态 Cookie 缓存生命周期对齐Cookie 缓存 maxAge 现在与会话 expiresIn 匹配,以防止缓存数据过期。

弃用

变更描述
OIDC Provider 插件已被 @better-auth/oauth-provider 替代。将在下一个次要版本中移除。

For the full list of changes, see the changelog.


迁移到 v1.6

For most users, upgrading is straightforward:

npx auth upgrade

Please review the 重要变更 section to confirm whether any breaking changes, behavior changes, or deprecations affect your setup.


我们未来如何运行 Better Auth

For a long time, all kinds of changes competed for the same release window. Bug fixes, additive improvements, large refactors, and breaking changes all shared the same release path, which meant a small fix might need to ship now, while still waiting on unrelated work.

Our guiding principle has always been simple. We want important fixes to ship quickly without losing predictability or backwards compatibility. There should be no surprises, and when an upgrade does require action, that action should be easy to understand and straightforward to perform.

v1.6 is a transitional release built around that principle. Here’s what that means in practice.

两条发布轨道

Important fixes should not wait on unrelated work.

Better Auth releases now flow through two tracks instead of one. When a change requires existing users to update code, config, or schema, that change ships first on the beta track.

  • main is the stable track. It ships bug fixes, security patches, additive improvements, and behavior changes that do not require user action. New features can also land here, provided they are well tested, non-breaking, and safe to adopt immediately.
  • next is the testing track. It ships new features, refactors, and breaking changes, giving users a testing period to adapt.

This split exists so important fixes can move quickly while still ensuring breaking changes do not land unannounced. As before, npm install better-auth will continue to get the latest stable release. To try the latest testing release, install with the @beta tag.

For contributors, release decisions now happen on the pull request itself. Changesets on each PR declare their release intent, and our automation routes the PR to the correct branch.

新功能请求

Discussion before code.

Going forward, every new feature request should start with the Feature request issue template instead of opening a pull request directly.

Submitting large PRs directly makes it difficult to review safely while keeping the existing system stable. Starting with an issue gives us a chance to shape scope, align on API shape, and schedule the work for the right release track. It also gives us a clearer way to communicate the roadmap, so contributors and users can understand where a feature is headed and when it might land.

Bug fixes, documentation improvements, and small additive changes can still be submitted directly as pull requests, just as before.

重构发布说明

Clarity matters as much as completeness.

Release notes are now grouped by package instead of being presented as one flat changelog. This helps you find the packages you actually use faster and decide whether a change affects you.

This is powered by Better Release, the automation tool we built for our internal release process. For maintainers, it reduces the human errors that tend to creep into release prep; for users, it produces more consistent and more readable release communication.

可信发布

Trust matters as much as speed.

Every npm package we release now uses OIDC trusted publishing through GitHub Actions. There are no long-lived release tokens sitting in CI waiting to be stolen, and every published artifact includes provenance that proves it came from the exact source commit and workflow that produced it.

This matters because most major incidents in the npm ecosystem have come from stolen credentials and supply-chain attacks, not malicious code in reviewed commits. Commit signing and contributor identity still matter, but for package consumers, verifiable artifact provenance is a stronger guarantee.

You can verify the Better Auth package locally:

terminal
npm audit signatures

贡献者

感谢所有为本次发布做出贡献的贡献者!