Zodを活用して安全に認証フローとAPIレスポンス取得を実現する方法
Zodを導入する恩恵の一つとして、ユーザー入力やAPIとのやり取りにおいて型とデータ整合性を保証できることがあります。
今回は、ログイン・登録・認証チェックといった典型的なフローにZodをどう活用するか、API側とフロントエンド側での活用例を交えてわかりやすく解説していきます。
認証リクエストのバリデーション(ログイン編)
まずはログインフォームの入力バリデーションから。
バックエンドのリクエスト検証とフロントの型定義を共通化します。
共通スキーマ定義(shared-schema/auth.ts)
tsimport { z } from "zod";
export const loginSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
export type LoginRequest = z.infer<typeof loginSchema>;
バックエンドでの検証(NestJSの例)
tsimport { loginSchema } from "@shared-schema/auth";
const body = await request.json();
const result = loginSchema.safeParse(body);
if (!result.success) {
return Response.json(
{ error: result.error.format() },
{ status: 400 }
);
}
// 認証処理へ
const { email, password } = result.data;
フロントエンドでのフォーム型として使用(React Hook Form)
tsimport { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { loginSchema, LoginRequest } from "@shared-schema/auth";
const { register, handleSubmit, formState } = useForm<LoginRequest>({
resolver: zodResolver(loginSchema),
});
ユーザー登録(Sign Up)のバリデーションと整合性チェック
ユーザー登録では、フィールド間の整合性が求められます。superRefineで実装可能です。
スキーマ定義(パスワード確認付き)
tsexport const signUpSchema = z
.object({
email: z.string().email(),
password: z.string().min(8),
confirmPassword: z.string(),
})
.superRefine(({ password, confirmPassword }, ctx) => {
if (password !== confirmPassword) {
ctx.addIssue({
path: ["confirmPassword"],
code: "custom",
message: "パスワードが一致しません",
});
}
});
export type SignUpRequest = z.infer<typeof signUpSchema>;
APIレスポンスの型安全化と整合性チェック
APIレスポンスの構造にもZodを活用できます。
これにより、サーバーから受け取ったデータの型安全性と妥当性を確保できます。
成功・エラー応答のUnion定義
tsconst successResponseSchema = z.object({
status: z.literal("ok"),
user: z.object({
id: z.string().uuid(),
name: z.string(),
email: z.string().email(),
}),
});
const errorResponseSchema = z.object({
status: z.literal("error"),
message: z.string(),
});
export const loginResponseSchema = z.union([
successResponseSchema,
errorResponseSchema,
]);
export type LoginResponse = z.infer<typeof loginResponseSchema>;
フロントエンドでのレスポンスチェック
tsconst res = await fetch("/api/login", {
method: "POST",
body: JSON.stringify(values),
});
const json = await res.json();
const result = loginResponseSchema.safeParse(json);
if (!result.success) {
throw new Error("レスポンス構造が不正です");
}
if (result.data.status === "ok") {
console.log("ようこそ", result.data.user.name);
} else {
alert("ログインエラー: " + result.data.message);
}
JWT付きセッションチェックなどの発展パターン
APIの認証チェックでも、Zodは活躍します。
例えばJWTのペイロード検証や、APIレスポンスが未ログイン・ログイン済で分かれる場合などに便利です。
JWTペイロード検証
tsconst jwtPayloadSchema = z.object({
sub: z.string().uuid(), // ユーザーID
exp: z.number(), // 有効期限
iat: z.number(), // 発行時刻
});
const decoded = jwt.verify(token, secret);
const result = jwtPayloadSchema.safeParse(decoded);
if (!result.success) {
throw new Error("トークンが無効です");
}
サーバーレスポンスの設計パターン一覧
| ケース | スキーマ設計例 |
|---|---|
| ログイン成功 | status + user |
| ログイン失敗 | status + message |
| セッション期限切れ | status: "unauthorized" + message |
| フィールドエラー | status: "validation_error" + errors[] |
| 任意フィールドのnull許容 | z.string().nullable() で対応 |
まとめ
Zodを用いることで、認証フローやAPI通信において次のような恩恵が得られます。
| メリット | 内容 |
|---|---|
| 型とバリデーションの一元管理 | リクエスト・レスポンス・フォームすべてで型を共有 |
| 実行時安全性の向上 | サーバー側でのパースエラーや構造違反を早期検出 |
| 変更耐性のある設計 | スキーマの中心化により変更がプロジェクト全体に自動反映 |
| 型の補完と検証の自動化 | IDE補完と安全なデータ操作が保証され、開発効率が向上 |
実運用に即した設計こそ、Zodの真価が発揮される場面です。
認証・認可・セッション管理といったセンシティブな領域にも、安心して導入できる強力なツールなためぜひ活用してみて下さい。
articleZod vs Ajv/Joi/Valibot/Superstruct:DX・速度・サイズを本気でベンチ比較
articleZod × OpenAPI:`zod-to-openapi` で契約からドキュメントを自動生成
articleZod で CSV/TSV インポートを安全に処理:パース → 検証 → 差分レポート
articleZod のブランド型(Branding)設計:メール・ULID・金額などの値オブジェクト化
articleZod クイックリファレンス:`string/number/boolean/date/enum/literal` 速見表
articleZod 導入最短ルート:yarn/pnpm/bun でのセットアップと型サポート
articleSvelte のコンパイル出力を読み解く:仮想 DOM なしで速い理由
articleTauri で Markdown エディタを作る:ライブプレビュー・拡張プラグイン対応
articleStorybook で“仕様が生きる”開発:ドキュメント駆動 UI の実践ロードマップ
articleshadcn/ui で B2B SaaS ダッシュボードを組む:権限別 UI と監査ログの見せ方
articleSolidJS の Control Flow コンポーネント大全:Show/For/Switch/ErrorBoundary を使い分け
articleRemix で管理画面テンプレ:表・フィルタ・CSV エクスポートの鉄板構成
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来