Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TSKaigi 2026 - Auth.jsからBetter Authへの 移行に見る「型とラ...

TSKaigi 2026 - Auth.jsからBetter Authへの 移行に見る「型とランタイム」の 設計思想の変化

このスライドは TSKaigi 2026 の登壇に使用したスライドのアーカイブになります。

チームラボでは、フロントエンドエンジニアを募集しています。
少しでも、チームラボにご興味をお持ち頂けましたら、採用ページをご覧頂けますと幸いです。
https://www.team-lab.com/recruit/

Avatar for teamLab

teamLab PRO

May 22, 2026

More Decks by teamLab

Other Decks in Technology

Transcript

  1. © teamLab Inc. 所属| 2 自己紹介 2 パッケージチーム フロントエンド班 宇根

    昇汰 Une Shota 2024年 新卒入社 3年目 家でできることが好き!
  2. © teamLab Inc. Auth.js と Better Auth 4 Webアプリの認証で広く使われてきた ライブラリ

    Auth.js では前身となる NextAuth から フレームワーク依存を排除した設計に 広げられた 特定のフレームワークに依存せず、 アプリ固有の認証モデルを拡張する プラグインが豊富 NextAuth の影響を受けて作られた 後発のライブラリ
  3. © teamLab Inc. 2025年 9月 Auth.js の開発が Better Auth チームに移行されるとの発表

    5 メンテナンス/開発を Better Auth チームが行う旨を発表(#13252) Auth.js 公式は Better Auth への移行を推奨するように この2つのライブラリで型はどう変わっているかを見る
  4. © teamLab Inc. App Server 認証成功後の情報の流れとライブラリの役割 7 DB Auth Runtime

    App Client - DB と接続し、セッションとして必要な情報を取得する - 取得した情報からアプリケーションに渡す情報を組み立てる - サーバー/クライアントサイドでセッションを取得するための関数の 提供
  5. © teamLab Inc. App Server 認証成功後の情報の流れとライブラリの役割 8 DB Auth Runtime

    App Client user.role セッションにアプリケーション固有のプロパティを追加 アプリケーションサーバー/クライアントに型安全に渡したい 実際の値と型情報をどのように渡すのか比較
  6. © teamLab Inc. Auth.js: 拡張した型を宣言し、ランタイムのコードを型に合わせる 9 App Server DB Auth

    Runtime App Client declare module "next-auth" { interface Session { user: { role: "user" | "admin"; } & DefaultSession["user"]; } interface User { role: "user" | "admin"; } }
  7. © teamLab Inc. Auth.js: 拡張した型を宣言し、ランタイムのコードを型に合わせる 10 App Server DB Auth

    Runtime App Client declare module "next-auth" { interface Session { user: { role: "user" | "admin"; } & DefaultSession["user"]; } interface User { role: "user" | "admin"; } } callbacks: { session({ session, user }) { session.user.role = user.role; return session; }, },
  8. © teamLab Inc. Auth.js: 拡張した型を宣言し、ランタイムのコードを型に合わせる 11 App Server DB Auth

    Runtime App Client 取得した session には session.user.role が含まれると推論される session.user.role: "user" | "admin" // Server Side const session = await auth(); // Client Side const { data: session } = useSession();
  9. © teamLab Inc. session.user.role: "user" | "admin" Auth.js: 型とランタイムの値のズレが生じうる 12

    App Server DB Auth Runtime App Client session は拡張済みの Session 型 → session に role を実際に含めずとも型エラーにならない // Server Side const session = await auth(); // Client Side const { data: session } = useSession(); callbacks: { session({ session, user }) { // roleを詰め忘れる // session.user.role = user.role; return session; }, },
  10. © teamLab Inc. Auth.js: 型とランタイムの値のズレが生じうる 13 App Server DB Auth

    Runtime App Client callbacks: { session({ session, user }) { // roleを詰め忘れる // session.user.role = user.role; return session; }, }, declare module "next-auth" { interface Session { user: { role: "user" | "admin"; } & DefaultSession["user"]; } } ランタイムの値を扱う箇所と型定義を行う箇所が独立しているため 両方を同期・更新する必要がある
  11. © teamLab Inc. Better Auth: config から型を推論 14 App Server

    DB Auth Runtime App Client export const auth = betterAuth({ user: { additionalFields: { role: { type: ["user", "admin"], input: false, }, }, }, })
  12. © teamLab Inc. Better Auth: config から型を推論 15 App Server

    DB Auth Runtime App Client export const auth = betterAuth({ user: { additionalFields: { role: { type: ["user", "admin"], input: false, }, }, }, }) const session = await auth.api.getSession({ headers: await headers(), }); session.user.role: "user" | "admin"
  13. © teamLab Inc. Better Auth: config から型を推論 16 App Server

    DB Auth Runtime App Client export const auth = betterAuth({ user: { additionalFields: { role: { type: ["user", "admin"], input: false, }, }, }, }) const session = await auth.api.getSession({ headers: await headers(), }); session.user.role: "user" | "admin" type Session = typeof auth.$Infer.Session;
  14. © teamLab Inc. Better Auth: config から型を推論 17 App Server

    DB Auth Runtime App Client auth インスタンスがランタイムと型推論の交点になる export const auth = betterAuth({ user: { // roleを詰め忘れる }, }) type Session = typeof auth.$Infer.Session;
  15. © teamLab Inc. 19 Auth.js 型を宣言する ↓ 型に合わせたレスポンスを作る Better Auth

    ランタイムを決める config を書く ↓ config を元に型を推論する 型とランタイムの SSOT(Single Source of Truth)を決める設計 設計思想の変化
  16. © teamLab Inc. 近年の TypeScript エコシステムにおける、フロントエンドバックエ ンド一体型のアプリケーション構成の台頭が理由にありそう 👀 設計思想の変化 20

    ただ、データが自分のアプリケーションとより密接に統合されていればいいのにと思 うこともありました。おそらく、それがあなたが目指しているところなのでしょう。 @bekacru はい、まさにそれが私たちの目指すところです。認証をアプリに密接に連携させるべ き理由はたくさんあると思います。 (省略) フロントエンドとバックエンドが一体となって強力な型システムを共有するフルス タックTypeScriptアプリの台頭に伴い、すべてのコンテキストを1か所にまとめてお くことがますます理にかなっていると言えるでしょう。 - Hacker News
  17. © teamLab Inc. Better Auth は複雑なアプリ固有の認証モデルを自分たちのアプリ ケーションに統合して扱うことが開発の目的の一つ ランタイムでの認証モデルを config に定義し、型まで推論する設計

    はフルスタック TypeScript アプリと認証ランタイムを統合する上で 相性がいい → サーバー/クライアントに認証モデルの変更が型レベルで伝播するため 設計思想の変化 21 (特に) フルスタック TypeScript アプリケーションに 認証ランタイムを統合する設計思想に変化した(...ように見える)
  18. © teamLab Inc. - Auth.js は追加フィールドの型を宣言し、型に合わせてランタイム の処理を追加する - Better Auth

    ではランタイムの処理を定義する config を書き、そこ から型を推論する - 近年台頭するフルスタック TypeScript アプリに強く統合できるよ うな設計に変化した(...のだと思う) まとめ 22
  19. © teamlab Inc. 宇根 昇汰 チームラボ パッケージチーム 所属 Auth.js から

    Better Auth への 移行に見る「型とランタイム」の 設計思想の変化 ありがとうございました