はじめに
業務で、ログインが必要なアプリに対してAPI経由でデータを登録するツールを使っています。
このツールは、設定ファイルに保存されたトークンを使ってAPIを叩く仕組みになっています。
{
"Token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIs...",
"CompanyID": "9999"
}
def get_api_header
{ "Authorization" => "Bearer #{token}" }
end
このコードを見ていて、いくつか疑問が湧いてきました。この記事では、その疑問を調べたことをまとめています。認証周りに詳しい方から見れば基本的な内容かもしれませんが、同じような疑問を持つ方の参考になれば幸いです。
疑問1: トークン1つでログインが必要なAPIを叩けるのは、セキュリティ的に大丈夫?
最初に思ったこと
設定ファイルにトークンを書いておくだけで、ログイン処理なしにAPIを叩ける。これって、もしトークンが漏れたら誰でもAPIを使えてしまうのでは...?
調べてわかったこと
トークン(特にJWT)は、単なる識別子ではなく**「署名付きの証明書」**のような役割を持っているようです。
JWT(JSON Web Token)とは
JWT(ジョット)は、「JSON形式の情報を含んだWebトークン」のことです。実際のJWTは長い文字列で、3つの部分で構成されています:
ヘッダー.ペイロード.署名
例えば、こんな見た目をしています:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIs...
これらはBase64でエンコードされているだけなので、デコードすると中身を読むことができます。
ヘッダー部分をデコードすると:
{
"alg": "RS256", // 署名アルゴリズム
"typ": "JWT" // トークンのタイプ
}
ペイロード部分をデコードすると:
{
"sub": "auth0|68ef9c2cee3c69d173de2dde", // ユーザーID
"iat": 1760610413, // 発行日時
"exp": 1760617613, // 有効期限
"scope": "openid profile email" // 権限
}
注意点として、JWTは暗号化されているわけではなく、単にエンコードされているだけです。つまり誰でも中身を読めるため、パスワードやクレジットカード番号などの機密情報は入れてはいけません。
この情報に対して、サーバーの秘密鍵で署名がされているため、第三者が内容を改ざんしても、サーバー側で検証時に弾かれる仕組みになっているそうです。
Bearer認証とは
Bearer認証は、HTTPのAuthorizationヘッダーでトークンを送信する標準的な方法です。「Bearer」は英語で「持参人」という意味で、「このトークンを持っている人は認証済み」という意味合いになります。
使い方はシンプルで、以下のような形式です:
Authorization: Bearer <トークン>
つまり、JWTは「何を送るか」(トークンの形式)で、Bearer認証は「どう送るか」(送信方法)という違いがあります。
セキュリティ面での対策
調べていくと、以下のような対策が取られていることがわかりました:
- 短い有効期限:トークンは2時間程度で期限切れになる
- HTTPS必須:通信を暗号化することで、トークンの盗聴を防ぐ
- 署名による検証:改ざんされたトークンは使えない
ただし、トークンが漏洩した場合、有効期限内は使われてしまう可能性があります。そのため、トークンはパスワードと同じくらい慎重に扱う必要があるようです。
疑問2: なぜ社内ツールのトークンは2時間で切れるの?
最初に思ったこと
このツールを使っていると、2時間経つと必ず401エラーが出て、手動でトークンを更新しないといけない。なぜこんな短い期限なんだろう?
調べてわかったこと
トークンに短い有効期限を設定するのは、セキュリティのためのようです。
もしトークンが漏洩した場合でも:
- 短い有効期限なら、被害を最小限に抑えられる
- 古いトークンが長期間使われ続けることを防げる
特に、このツールのように設定ファイルにトークンを保存する場合:
- ファイルが誤ってGitにコミットされるリスク
- 他の人がファイルにアクセスできるリスク
- バックアップから古いトークンが復元されるリスク
こういったリスクを考えると、トークンの有効期限は短い方が安全なようです。
では、なぜブラウザでログインすると2時間で切れないのか?それが次の疑問につながります。
疑問3: ブラウザでのログインは2時間で切れないのはなぜ?
最初に思ったこと
同じシステムにブラウザでログインすると、2時間経っても使い続けられる。APIツールとブラウザで何が違うんだろう?
調べてわかったこと
ブラウザでのログインでは、リフレッシュトークンという仕組みが使われているようです。
アクセストークンとリフレッシュトークン
実際のシステムでは、2種類のトークンを使い分けているそうです:
| トークンの種類 | 有効期限 | 用途 |
|---|---|---|
| アクセストークン | 2時間程度 | API呼び出しに使用 |
| リフレッシュトークン | 数日〜数ヶ月 | 新しいアクセストークンを取得 |
アクセストークンは、実際のAPI呼び出しに使う短命のトークンです。セキュリティのため短い有効期限が設定されています。
リフレッシュトークンは、新しいアクセストークンを取得するための長命のトークンです。これがあることで、ユーザーは頻繁に再ログインする必要がなくなります。
図で表すとこのようになります:
【初回ログイン】
ユーザー
↓ ID/パスワード
認証サーバー
↓ 2種類のトークンを発行
├─ アクセストークン(2時間)
└─ リフレッシュトークン(30日)
↓
クライアント(両方を保存)
【2時間後、アクセストークンが期限切れ】
クライアント
↓ リフレッシュトークンを送信
認証サーバー
↓ 新しいアクセストークンを発行
クライアント(更新)
↓
✓ ユーザーは再ログイン不要
【30日後、リフレッシュトークンも期限切れ】
クライアント
↓
認証サーバー
↓ エラー
クライアント
↓
✗ 再ログインが必要
ブラウザとAPIツールの違い
疑問2と疑問3をまとめると、以下のように動作が異なります:
【ブラウザでログインした場合】
1. ログイン時に2種類のトークンを取得
- アクセストークン(2時間)
- リフレッシュトークン(長期間)
2. 両方ともブラウザのCookieなどに保存
3. アクセストークンが切れたら...
→ アプリが自動的にリフレッシュトークンを使用
→ 新しいアクセストークンを取得
→ ユーザーは何も気づかない
【APIツールの場合】
1. 設定ファイルにアクセストークンのみ保存
2. アクセストークンが切れたら...
→ リフレッシュトークンがない
→ 401エラー
→ 手動で更新が必要
動作の違いを図で表すと:
【ブラウザ - リフレッシュトークンあり】
┌────────────────────────────────┐
│ Cookie/LocalStorage │
├────────────────────────────────┤
│ ✓ アクセストークン(2時間) │
│ ✓ リフレッシュトークン(30日) │
└────────────────────────────────┘
↓
2時間経過...
↓
┌────────────────────────────────┐
│ アクセストークン期限切れ │
└────────────────────────────────┘
↓
自動的に...
↓
┌────────────────────────────────┐
│ リフレッシュトークンで │
│ 新しいアクセストークンを取得 │
└────────────────────────────────┘
↓
✓ ログイン状態継続
【APIツール - アクセストークンのみ】
┌────────────────────────────────┐
│ api_config.json │
├────────────────────────────────┤
│ ✓ アクセストークンのみ(2時間) │
│ ✗ リフレッシュトークンなし │
└────────────────────────────────┘
↓
2時間経過...
↓
┌────────────────────────────────┐
│ アクセストークン期限切れ │
└────────────────────────────────┘
↓
リフレッシュトークンがない...
↓
┌────────────────────────────────┐
│ ✗ 401エラー! │
│ 手動で新しいトークンを │
│ 取得する必要がある │
└────────────────────────────────┘
つまり、リフレッシュトークンの有無が大きな違いのようです。
APIツールの場合、設定ファイルに長期間有効なリフレッシュトークンを保存するのはセキュリティリスクが高いため、アクセストークンのみを使う設計になっているのかもしれません。
疑問4: 銀行アプリが15分で切れるのは何が違うの?
最初に思ったこと
銀行や証券会社のアプリは、15分くらい触らないとログインが切れる。これは今までの話と何が違う?
調べてわかったこと
銀行アプリは、
- リフレッシュトークンの有効期限を極端に短くする
- アイドルタイムアウトの仕組みを使っている
- cookieの有効期限を設定する
などの方法で使っていないとログインが切れるようになっているようです。
アイドルタイムアウトの場合は、以下のようになります。
【一般的なアプリ】
トークン発行 ────────────────► 2時間後に期限切れ
↑ ↑
ログイン時 時間経過のみ
→ 何もしなくても、操作しても、2時間は有効
【銀行アプリ】
トークン発行 ──────► 最後の操作から15分後に無効化
↑ ↑ ↑
ログイン時 操作 また操作
(タイマー (タイマー
リセット) リセット)
→ 操作するたびにタイマーがリセットされる
→ 15分間何もしないと自動ログアウト
なぜ銀行は厳しいの?
お金が動くシステムでは、スマホを置き忘れたり、のぞき見されたりするリスクが高いため、より短い時間でログアウトさせているようです。
| サービスの種類 | タイムアウト | 理由 |
|---|---|---|
| 銀行・証券 | 5〜15分 | お金が動く、被害が大きい |
| 社内システム | 30分〜1時間 | 機密情報保護 |
| ECサイト | 30分〜2時間 | 再決済が必要 |
| SNS | 制限なし〜数日 | 金銭的被害は少ない |
実際には、銀行アプリは以下の2つを組み合わせているそうです:
- トークンの有効期限(24時間など):長期的な漏洩リスク対策
- アイドルタイムアウト(15分):短期的な放置リスク対策
まとめ
業務でAPIツールを使っていて湧いた疑問を調べてみました。
- トークンは署名付きの証明書のようなもので、改ざんできない仕組みになっている
- 2時間という短い期限は、漏洩時のリスクを減らすため
- リフレッシュトークンがあれば自動更新ができる
- 銀行アプリは「操作していない時間」をカウントする別の仕組みを使っている
認証周りは奥が深く、まだまだ理解できていない部分も多いですが、今回調べたことで少し仕組みがわかってきました。もし内容に誤りがあれば、コメントで教えていただけると嬉しいです。