提示:本网站现在为维护调试状态

JWT 認証セキュリティ + OAuth2 vs SAML

Choyeon
Choyeon
2026年9月12日 1 分で読了 273 閲覧
458 字 2,981 文字 更新日 2026年11月8日
JWT 認証セキュリティ + OAuth2 vs SAML
目次

JWT Security Best Practices + OAuth2 vs SAML

JWT is ubiquitous for stateless cross-service convenience but sloppy config is a top attack target. Modern systems also need third-party login or enterprise SSO so choosing the right federation protocol is mandatory architect knowledge.

JWT Secure Implementation Checklist

Never sign tokens client-side with symmetric HMAC secrets. Production uses RS256/ES256 asymmetric - public keys verify openly. Whitelist only allowed algorithms; compare iss/aud with timingSafeEqual to prevent timing oracles; track jti blacklists for revocation.

import { createSign, createVerify, randomBytes, timingSafeEqual } from "node:crypto";

export interface JwtConfig {
    algorithm: "RS256";
    privateKeyPem: string;
    publicKeyPem: string;
    issuer: string;
    audience: string;
    accessTokenTtlSec: number;
    allowedAlgos: readonly string[];
}
export interface TokenPayload {
    sub: string; scopes: readonly string[]; jti: string;
    exp: number; nbf: number; iat: number; iss: string; aud: string;
}
const B64 = {
    enc: (b: Buffer) => b.toString("base64url"),
    dec: (s: string) => Buffer.from(s, "base64url"),
};
const DENIED = new Set<string>();

export function createJwt(cfg: JwtConfig, claims: Partial<TokenPayload> & { sub: string; scopes: readonly string[] }): string {
    const now = Math.floor(Date.now() / 1000);
    const header = { alg: cfg.algorithm, typ: "JWT", kid: "k1" };
    const payload: TokenPayload = {
        sub: claims.sub, scopes: claims.scopes,
        jti: randomBytes(16).toString("hex"),
        iat: now, nbf: now, exp: now + cfg.accessTokenTtlSec,
        iss: cfg.issuer, aud: cfg.audience,
    };
    const input = `${B64.enc(Buffer.from(JSON.stringify(header)))}.${B64.enc(Buffer.from(JSON.stringify(payload)))}`;
    const s = createSign("RSA-SHA256"); s.update(input);
    return `${input}.${B64.enc(s.sign(cfg.privateKeyPem))}`;
}

export function verifyJwt(cfg: JwtConfig, token: string): TokenPayload {
    const parts = token.split(".");
    if (parts.length !== 3) throw new Error("malformed");
    const [hB64, pB64, sB64] = parts;
    const header = JSON.parse(B64.dec(hB64).toString());
    if (!cfg.allowedAlgos.includes(header.alg) || header.alg === "none") throw new Error("alg not allowed");
    const ver = createVerify("RSA-SHA256"); ver.update(`${hB64}.${pB64}`);
    if (!ver.verify(cfg.publicKeyPem, B64.dec(sB64))) throw new Error("signature mismatch");
    const p = JSON.parse(B64.dec(pB64).toString()) as TokenPayload;
    if (!timingSafeEqual(Buffer.from(p.iss), Buffer.from(cfg.issuer))) throw new Error("iss");
    if (p.aud !== cfg.audience) throw new Error("aud");
    const now = Math.floor(Date.now() / 1000);
    if (p.exp < now) throw new Error("expired");
    if (p.nbf > now) throw new Error("not yet valid");
    if (DENIED.has(p.jti)) throw new Error("revoked");
    return p;
}

OAuth2 / OIDC / SAML Compared

OAuth2 is an authorization framework, NOT authentication. OpenID Connect adds id_token on top of OAuth2 to deliver real login. SAML 2.0 is classic enterprise federation with XML payloads - compatible but clunky on mobile.

Feature OAuth2 + PKCE OIDC (over OAuth2) SAML 2.0
Nature Delegated authorization User authentication Federated authN+authZ
Best fit Mobile / SPA Web/Mobile/APIs Enterprise internal SSO
Credentials access_token only access_token + id_token (JWT) SAML Assertion (XML)
Security Requires PKCE against CSRF Native nonce support Signed XML, complex flows
Mobile UX Great (app transitions) Great Poor (many redirects)
Integration complexity Medium Low High (metadata exchange)

Best Practices

If JWTs carry sensitive scope: short TTL (5-15 min) + refresh token rotation. SPAs should store refresh tokens in HttpOnly cookies to sidestep XSS. Standardize on OIDC for any third-party login scenario.

X微博Telegram

筆者について

投票

你最希望 Rosetta 优先加入哪项功能?

社区投票(演示数据,可后台删除)

コメント (4)

0 / 3000
画画的小鱼
画画的小鱼fishgallery.art2026年9月21日

有个小问题:你文中用的是 @Async 注解,这个默认用的是 SimpleAsyncTaskExecutor,生产环境是不是最好手动配一个线程池?

考研加油鸭
考研加油鸭kaoyan-journey.xyz2026年9月21日

作为一个刚入行的后端新人,这篇文章帮我理清了好多概念,谢谢博主持续输出高质量内容!

代码幽灵
代码幽灵ghostdev.blog2026年9月20日

哈哈,楼主的踩坑经历和我一模一样!我当时就是没注意到这个配置,排查了整整两天,看到这篇文章泪目了。

游戏策划阿哲
游戏策划阿哲2026年9月20日

写得太好了,终于搞懂了分布式事务的几种方案区别,收藏了!

関連記事

GraphQL vs REST:7つの視点から深く比較

GraphQL vs REST:7つの視点から深く比較

APIスタイル選択迷宮を終わらせる:ネットワーク効率・DX・進化コスト・キャッシュ・型安全性・セキュリティ・エコシステムの7次元で比較。明確なデシジョンツリーとハイブリッド構成を提示。

1 分で読了
Prompt Engineering 入門:Few-Shot + CoT + 構造化出力

Prompt Engineering 入門:Few-Shot + CoT + 構造化出力

Prompt Engineering体系入門:3つのコアテクニック——Few-Shot例示学習でドメインスタイル注入、Chain-of-Thoughtで複雑推論誘導、JSON Schema強制構造化出力で下流システム連携。実テンプレートとアンチパターン集付き。

1 分で読了
CQRS + Event Sourcing アーキテクチャ解説

CQRS + Event Sourcing アーキテクチャ解説

高度な分散パターン:CQRS読み書き分離でクエリ性能、Event Sourcingはイベントを唯一の源として監査+時間遡行。一貫性・スナップショット・べき等とアンチパターンを解説。

1 分で読了
テストピラミッド:単体/結合/E2E 比率と実践

テストピラミッド:単体/結合/E2E 比率と実践

テストピラミッド体系解説:下層 単体テスト(多数・高速・Mock分離)、中層 結合テスト(実DB/メッセージ協調)、上層 E2E(少数・重要ユーザーフロー)。推奨比率 70/20/10、カバレッジ指標と実践ガイド。

1 分で読了
FastAPI クイックスタート - 高性能 REST API の構築

FastAPI クイックスタート - 高性能 REST API の構築

FastAPI は現代の Python Web フレームワークの中でも傑出しており、型ヒントによる自動ドキュメント生成、非同期サポート、Node.js 並みのパフォーマンスを提供します。この実践ガイドでは、ルート定義、リクエスト検証、依存性注入、データベース統合を含む完全な CRUD API をゼロから構築します。

この記事は閲覧パスワードが必要です 4 分で読了
Alembic ディープガイド:DBマイグレーション + 自動生成 + ブランチマージ

Alembic ディープガイド:DBマイグレーション + 自動生成 + ブランチマージ

SQLAlchemy公式マイグレーションツール Alembic 完全ガイド:env.py設定、autogenerateによるモデル変更検出(カラム・インデックス・制約)、バッチスクリプト、ダウングレードロールバック戦略、複数人開発時のマイグレーションコンフリクトとhead分岐マージの標準SOP、本番デプロイチェックリスト付き。

1 分で読了