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つのロールが定義されています。
- リソースオーナー(Resource Owner): 保護されたリソースの所有者、通常はエンドユーザー
- クライアント(Client): リソースオーナーの代わりにリソースにアクセスしたいアプリケーション
- 認可サーバー(Authorization Server): リソースオーナーの認証を行い、アクセストークンを発行するサーバー
- リソースサーバー(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認証の仕組みを理解し、自社に最適な形で導入することで、安全で使いやすい認証システムを構築できます。
まずは小さく始めて、段階的に拡張していく――そのアプローチが、中小企業のデジタル化成功の鍵となります。