OAuth2.0とJWT認証の仕組みを図解で解説|初心者向け実装ガイド

kento_morota 15分で読めます

OAuth2.0とJWT認証の基本概念

「ログイン機能を強化したいけれど、セキュリティも気になる」――中小企業のWeb担当者や経営者の方から、こうした声をよく耳にします。

現代のWebシステムにおいて、OAuth2.0とJWT(JSON Web Token)は、安全で使いやすい認証・認可の仕組みを実現するための重要な技術です。この記事では、これらの仕組みを図解を交えながら、初心者の方にもわかりやすく解説します。

OAuth2.0とJWTの役割:認証と認可の違い

まず理解すべきは、この2つの技術が異なる役割を持つことです。

OAuth2.0は「認可(Authorization)」のための標準的なプロトコルです。一方、JWTは「情報を安全にやり取りするためのトークン形式」です。

  • 認証(Authentication): 「あなたは誰ですか?」を確認すること
  • 認可(Authorization): 「あなたに何を許可しますか?」を決定すること

具体例で考えてみましょう。あなたがアプリで「Googleアカウントでログイン」を選択したとき、アプリは直接あなたのGoogleパスワードを受け取ることなく、Googleから「このユーザーの基本情報にアクセスしてよい」という許可(認可)を得ます。これがOAuth2.0の仕組みです。

そして、この許可証として発行されるのがトークンであり、その形式としてJWTが広く使われています。

なぜ今この技術が重要なのか

OAuth2.0とJWTが注目される背景には、ビジネス環境の変化があります。

1. マルチデバイス対応の必要性
顧客や従業員が、PC、スマートフォン、タブレットなど様々なデバイスからアクセスする時代です。JWTなら統一的に扱えます。

2. 外部サービスとの連携が当たり前に
複数のSaaSツールを組み合わせて使うことが一般的になりました。OAuth2.0があれば、安全に外部サービスと連携できます。

3. 開発コストと期間の削減
これらの技術は既に多くのライブラリやサービスで実装されています。標準的な仕組みを採用することで、開発期間を短縮し、コストを抑えられます

OAuth2.0の仕組みを理解する

OAuth2.0の仕組みを理解するには、登場人物(ロール)と、それぞれがどのように連携するかを把握することが重要です。

OAuth2.0の4つの役割

OAuth2.0では、以下の4つのロールが定義されています。

  1. リソースオーナー(Resource Owner): 保護されたリソースの所有者、通常はエンドユーザー
  2. クライアント(Client): リソースオーナーの代わりにリソースにアクセスしたいアプリケーション
  3. 認可サーバー(Authorization Server): リソースオーナーの認証を行い、アクセストークンを発行するサーバー
  4. リソースサーバー(Resource Server): 保護されたリソースを保持し、アクセストークンに基づいてリソースを提供するサーバー

実際のビジネスシーンでは、自社の顧客管理システム(クライアント)が、お客様(リソースオーナー)の許可を得て、Googleカレンダー(リソースサーバー)から予定情報を取得する、といった形で活用されます。

認可コードフローの流れ

最も一般的で安全な認可コードフローを例に、実際の流れを見ていきましょう。

ステップ1:認可リクエスト
ユーザーがクライアントアプリで「Googleアカウントでログイン」をクリックすると、認可サーバーのログイン画面にリダイレクトされます。

ステップ2:ユーザー認証と同意
ユーザーがログインし、「このアプリにカレンダーの読み取り権限を与えますか?」という画面で「許可」をクリックします。

ステップ3:認可コードの発行
認可サーバーが認可コードを発行し、指定されたリダイレクトURIにユーザーを戻します。

ステップ4:アクセストークンの取得
クライアントアプリが、受け取った認可コードを使って、認可サーバーにアクセストークンをリクエストします(この通信はサーバー間で行われ、ユーザーには見えません)。

ステップ5:リソースへのアクセス
取得したアクセストークンを使って、リソースサーバーから必要な情報を取得します。

このフローの利点は、クライアントアプリがユーザーのパスワードを一切扱わない点です。

アクセストークンとリフレッシュトークン

OAuth2.0では、2種類のトークンが使われます。

アクセストークン(Access Token)
- リソースにアクセスするための短期的な認証情報
- 有効期限は通常1時間程度と短い
- 漏洩した場合の被害を最小限に抑えるため

リフレッシュトークン(Refresh Token)
- アクセストークンの有効期限が切れたときに、新しいアクセストークンを取得するためのトークン
- 有効期限は長期(数週間〜数ヶ月)
- より厳重に保管する必要がある

この2段階の仕組みにより、セキュリティと利便性のバランスが取れています。

主要な認可フロー

OAuth2.0には、用途に応じて複数の認可フローが定義されています。

1. 認可コードフロー(Authorization Code Flow)
- 最も安全で推奨される方式
- サーバーサイドのWebアプリケーション向け

2. クライアントクレデンシャルフロー(Client Credentials Flow)
- ユーザーが介在しない、サーバー間通信向け
- バッチ処理やシステム間連携に使用

選択のポイント
- Webアプリケーション・モバイルアプリ → 認可コードフロー(PKCE拡張付き)
- サーバー間通信 → クライアントクレデンシャルフロー

中小企業の場合、まずは認可コードフローを理解し、実装することをお勧めします。

JWTの構造と仕組み

JWTは一見複雑に見えますが、その構造を理解すれば、なぜ効率的で安全なのかがわかります。

JWTの3つの構成要素

JWTは、ドット(.)で区切られた3つの部分から構成されています。

ヘッダー.ペイロード.署名

1. ヘッダー(Header)
トークンのタイプと署名アルゴリズムを示します。

{
  "alg": "HS256",
  "typ": "JWT"
}

2. ペイロード(Payload)
実際に送信したいデータ(クレーム)を含みます。

{
  "sub": "1234567890",
  "name": "山田 太郎",
  "iat": 1516239022,
  "exp": 1516242622
}

標準的なクレーム:
- sub:ユーザーID
- iat:発行日時
- exp:有効期限
- iss:発行者

3. 署名(Signature)
ヘッダーとペイロードが改ざんされていないことを保証します。

この3層構造により、情報の透明性と改ざん検知を両立しています。

エンコードと暗号化の違い

重要なポイントとして、JWTは暗号化ではなくBase64 URLエンコードされています。

JWTのペイロードは誰でもデコードして読めるため、機密情報(パスワード、クレジットカード番号等)を含めてはいけません。

中小企業のシステム開発では、JWTに含める情報の選定が重要です。必要最小限の情報だけを含め、機密情報は別途サーバーで管理する設計が推奨されます。

署名検証による安全性

JWTの安全性の核心は、署名による改ざん検知にあります。

署名検証の流れ
1. クライアントがJWTトークンをサーバーに送信
2. サーバーがヘッダーとペイロードを取り出す
3. サーバーが持つ秘密鍵で署名を再計算
4. 再計算した署名とトークンの署名を比較
5. 一致すれば正当、不一致なら改ざんされている

実装例(Node.jsの場合)

const jwt = require('jsonwebtoken');
const SECRET_KEY = process.env.JWT_SECRET;

// JWTの生成
const token = jwt.sign(
  { userId: 123, name: '山田 太郎' },
  SECRET_KEY,
  { expiresIn: '1h' }
);

// JWTの検証
try {
  const decoded = jwt.verify(token, SECRET_KEY);
  console.log(decoded);
} catch (error) {
  console.error('トークンが無効です');
}

重要なポイント
- 秘密鍵は絶対に外部に漏らさない
- 環境変数で管理し、コードに直接書かない
- 定期的に秘密鍵をローテーションする

JWTのメリットとデメリット

メリット
- ステートレス:サーバー側でセッション情報を保持する必要がない
- 自己完結型:トークン内に必要な情報が含まれ、データベース問い合わせが不要
- マイクロサービスとの相性が良い:複数のサービス間で認証情報を共有しやすい
- モバイルアプリに最適:Cookieに依存しない

デメリット
- トークンのサイズが大きい:毎回のリクエストで送信されるため、帯域を消費
- 発行後の無効化が困難:有効期限まではトークンが有効
- ペイロードは暗号化されていない:機密情報を含められない

中小企業での判断基準
- JWTが適している場合:API中心のシステム、モバイルアプリ、マイクロサービス
- 従来のセッションが適している場合:単一のWebアプリケーション、即座のログアウトが必須

OAuth2.0とJWTの実践的な組み合わせ

実際のシステムでは、OAuth2.0とJWTを組み合わせて使います。

OAuth2.0のトークンとしてJWTが使われる理由

OAuth2.0の仕様自体は、アクセストークンの形式を規定していません。しかし、実際にはJWT形式が広く採用されています。

1. 検証が効率的
- 従来の不透明トークン:リソースサーバーが毎回認可サーバーに問い合わせる必要がある
- JWT形式:リソースサーバーが署名を検証するだけで済む

2. 必要な情報がトークンに含まれる
JWTにはユーザーID、権限、有効期限、発行者情報を含められるため、リソースサーバーはトークンだけで認可判断ができます

3. マイクロサービスアーキテクチャに最適
各サービスが独立してトークンを検証でき、認可サーバーがボトルネックになりません。

実装パターン

実際の実装では、以下のような流れになります。

ステップ1:認可サーバーでJWTアクセストークンを生成

const jwt = require('jsonwebtoken');

app.post('/oauth/token', (req, res) => {
  const accessToken = jwt.sign(
    {
      sub: userId,
      scope: 'read:calendar write:calendar',
      iss: 'https://auth.yourcompany.com'
    },
    process.env.JWT_SECRET,
    { expiresIn: '1h' }
  );

  res.json({
    access_token: accessToken,
    token_type: 'Bearer',
    expires_in: 3600
  });
});

ステップ2:リソースサーバーでJWTを検証

const authenticateJWT = (req, res, next) => {
  const authHeader = req.headers.authorization;

  if (authHeader) {
    const token = authHeader.split(' ')[1];

    jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
      if (err) {
        return res.sendStatus(403);
      }
      req.user = decoded;
      next();
    });
  } else {
    res.sendStatus(401);
  }
};

app.get('/api/calendar', authenticateJWT, (req, res) => {
  const userId = req.user.sub;
  const calendar = getCalendar(userId);
  res.json(calendar);
});

このパターンにより、シンプルかつ安全なAPI認証が実現できます。

セキュリティのベストプラクティス

実装時に押さえておきたいセキュリティのポイントを解説します。

JWTの安全な保管方法

フロントエンドでの保管場所
- LocalStorage:XSS攻撃に脆弱
- Cookie(HttpOnly, Secure属性付き):XSS攻撃から保護できるが、CSRF対策が必要
- 推奨:短期のアクセストークンはメモリ、長期のリフレッシュトークンはHttpOnly Cookieに保存

トークンの有効期限設定

ベストプラクティス
- アクセストークン:15分〜1時間
- リフレッシュトークン:1週間〜1ヶ月
- 有効期限は業務要件とセキュリティ要件のバランスで決定

署名アルゴリズムの選択

推奨アルゴリズム
- HS256(HMAC + SHA-256):シンプルで高速、単一サーバー向け
- RS256(RSA + SHA-256):公開鍵暗号方式、マイクロサービス向け

注意点
- alg: "none"は絶対に使用しない
- アルゴリズムの検証を必ず実装する

よくある脆弱性と対策

1. トークンの漏洩
- 対策:HTTPSの使用、短い有効期限、適切な保管場所

2. CSRF攻撃
- 対策:CSRFトークンの併用、SameSite Cookie属性の設定

3. XSS攻撃
- 対策:入力値のサニタイズ、Content Security Policyの設定

中小企業での実装ガイド

実際に導入する際の選択肢と判断基準を解説します。

自社開発 vs 認証サービス利用

認証サービス利用が適している場合
- 開発リソースが限られている
- 早期にサービスを立ち上げたい
- セキュリティの専門知識が社内にない

自社開発が適している場合
- 独自の認証フローが必要
- 既存システムとの深い統合が必要
- ランニングコストを抑えたい

主要な認証サービスの特徴

Auth0
- 豊富な機能と柔軟性
- 日本語ドキュメントあり
- 月額:$0〜(無料枠あり)

Firebase Authentication
- Googleのサービスと連携しやすい
- モバイルアプリに最適
- 月額:従量課金(無料枠あり)

AWS Cognito
- AWSサービスとの統合が容易
- スケーラビリティが高い
- 月額:従量課金(無料枠あり)

最小限の実装で始める方法

ステップ1:要件の明確化
- 誰がログインするか(顧客、従業員、パートナー)
- どのデバイスからアクセスするか
- 外部サービスとの連携が必要か

ステップ2:認証サービスの選定
- 無料枠のある認証サービスで試作
- 必要最小限の機能で開始

ステップ3:段階的な拡張
- まずはメール・パスワード認証
- 次にソーシャルログイン追加
- 最後に多要素認証を検討

まとめ

重要ポイントの振り返り

OAuth2.0とJWTの本質
- OAuth2.0は「認可」の仕組み、JWTは「トークン形式」
- 組み合わせることで安全で効率的な認証・認可システムを実現
- パスワードを第三者に渡さず、安全に外部サービスと連携できる

実装時の重要ポイント
- 認可コードフローを基本とする
- JWTには機密情報を含めない
- 秘密鍵の管理を厳重に行う
- 適切な有効期限を設定する

自社に合った認証システムの選び方

小規模・スタートアップ
- 認証サービス(Auth0、Firebase等)の利用を推奨
- 開発期間とコストを大幅に削減できる

中規模・独自要件あり
- 認証サービスをベースに、必要な部分のみカスタマイズ
- 段階的に自社開発に移行する選択肢も

大規模・高度なセキュリティ要件
- 自社開発も検討
- ただし、セキュリティ専門家のレビューを必須とする

中小企業にとって重要なのは、「大きすぎず、小さすぎない、ちょうどいいデジタル化」を実現することです。OAuth2.0とJWT認証の仕組みを理解し、自社に最適な形で導入することで、安全で使いやすい認証システムを構築できます。

まずは小さく始めて、段階的に拡張していく――そのアプローチが、中小企業のデジタル化成功の鍵となります。

#OAuth2.0#JWT#認証
共有:

ちょっとした業務の悩みも、気軽にご相談ください。

まずは話だけ聞いてもらう