JWTって何?わかりやすく解説

ログインしたのに、ページを移動したら「もう一度ログインしてください」って表示されたことない?あるいは、アプリを使ってて「なんで毎回パスワード入れなくていいんだろう?」って思ったことない?実はその裏側には、ちゃんと「あなたが誰か」を証明する仕組みがあるんだ。その仕組みのひとつが JWT(ジェイダブリューティー) っていう技術。この記事を読めば、JWTがどんなものか、なんで便利なのか、しっかりわかるよ。

JWTってよく聞くけど、なんか難しそう…。結局なんなの?

JWTは一言でいうと「デジタルの身分証明書」だよ。ログインしたときにサーバーから「はい、あなたはAさんです」という証明書をもらって、それを次のアクセスのときに見せることで「私はAさんです」って証明できるんだ。
でも、その証明書って偽造できないの?自分で「私は管理者です」って書き換えたら?

いいところに気づいたね!JWTには「署名(しょめい)」がついてるんだ。つまり、サーバーだけが知ってる秘密の鍵で「このデータは本物ですよ」ってハンコを押すようなもの。書き換えると署名が合わなくなるから、すぐバレるんだよ。
じゃあ、その証明書ってどこに保存するの?スマホの中?

アプリやサービスによって違うんだけど、よくあるのは「ブラウザのローカルストレージ」や「Cookie(クッキー)」に保存する方法だよ。スマホアプリならアプリの中に保存することが多いかな。どこに保存するかで、セキュリティのリスクも変わってくるんだ。
なんでCookieじゃなくてわざわざJWTを使うの?

昔ながらのCookieだと、サーバー側で「誰がログイン中か」のリストを管理しないといけなかったんだ。でもJWTはトークン自体に情報が入ってるから、サーバーがリストを持たなくてもいい。つまり、サーバーを何台に増やしても同じように動くっていうメリットがあるんだよ。
📝 3行でまとめると
  1. JWTは デジタルの身分証明書 で、ログイン後に「あなたが誰か」を証明するために使われるよ
  2. データには 署名 がついているので、改ざんしてもすぐバレる仕組みになっているよ
  3. サーバー側でログイン情報を管理しなくていいので、大規模なシステム でも使いやすいのが特徴だよ
目次

もうちょっと詳しく

JWTは「JSON Web Token(ジェイソン ウェブ トークン)」の略で、JSONというデータ形式を使ったトークン、つまり「認証用の文字列」のことだよ。JWTは3つのパーツ(ヘッダー・ペイロード・署名)をドット「.」でつないだ文字列として表現されるんだ。見た目は「xxxxx.yyyyy.zzzzz」みたいな感じで、一見なんのことかわからないけど、Base64という方式でエンコード、つまり変換されてるだけで、デコード(元に戻す)すれば中身を読めるよ。サーバーは受け取ったJWTの署名を検証することで、「このトークンは本物か?改ざんされてないか?」を確認できるんだ。大事なのは、JWTは誰でも中身を「読める」けど「書き換えられない」という点。署名があるから、改ざんはすぐバレるんだよ。

💡 ポイント
JWTは「見られてもOK、でも書き換えNG」な仕組み。パスワードなどの秘密情報はペイロードに入れないようにしよう!

⚠️ よくある勘違い

❌ 「JWTは暗号化されてるから、中身を見られない」
→ JWTはBase64でエンコードされてるだけで、暗号化ではないよ。デコードすれば誰でも中身を読めるんだ。
⭕ 「JWTは改ざんを防ぐための署名がついているが、中身は誰でも読める」
→ 署名によって「書き換え」は検知できるけど、「読む」のは誰でもできる。だからパスワードや個人情報はJWTに入れちゃダメ!
なるほど〜、あーそういうことか!

[toc]

JWTってそもそもなに?基本をおさえよう

「トークン」って何?

JWTを理解するには、まず「トークン」という言葉を知っておく必要があるよ。トークンとは、つまり「本人確認のための合言葉のような文字列」のことだ。

イメージしてみてほしいんだけど、映画館に入るときのチケットってあるじゃない?あのチケットがあれば「この人は正規にお金を払って入る権利がある人だ」って証明できるよね。JWTはまさにデジタル版のチケットなんだ。ログインに成功したら「はい、これがあなたのチケットです」とサーバーからJWTをもらって、次からはそのJWTを見せるだけで「この人はログイン済みだ」ってわかるようになるんだよ。

JWTの正式名称と読み方

JWTは「JSON Web Token」の略で、「ジェイダブリューティー」または「ジョット」と読むこともあるよ。JSONはつまり「キーと値のペアでデータを表すデータ形式」のことで、たとえば {"name": "田中", "role": "admin"} みたいな書き方のことだ。このJSONを使ってWebの認証(つまり「あなたが誰か確認する仕組み」)に使えるようにしたのがJWTってわけだよ。

JWTは2015年にRFC 7519として標準化されていて、今では世界中のWebサービスやアプリで広く使われてる技術なんだ。GitHubとかGoogleとかもJWTを使ってるよ。

JWTの3つのパーツを解剖しよう

ヘッダー(Header)

JWTは「ヘッダー」「ペイロード」「署名」の3つのパーツからできてて、それぞれをドット「.」でつないだ文字列になってるよ。たとえば実際のJWTはこんな見た目だ:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IuWPjOS6jiIsInJvbGUiOiJ1c2VyIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

なんか暗号みたいだよね。でも怖くないよ。一番最初のパーツ(ドットの前)がヘッダーで、Base64でデコードするとこんな感じになるよ:

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

これはつまり「このJWTはHS256という署名アルゴリズムを使ってますよ」という説明書みたいなものだ。アルゴリズムとは、つまり「どんな計算方法でハンコを押したか」ということだよ。

ペイロード(Payload)

2番目のパーツがペイロードで、ここに実際の情報が入ってるんだ。「ペイロード」とはつまり「荷物の中身」という意味で、トークンに乗せたいデータを格納する部分だよ。デコードすると:

{"sub": "1234567890", "name": "田中", "role": "user", "exp": 1716239022}

こんな感じで、ユーザーのID・名前・権限・有効期限(expはexpirationの略で「いつまで有効か」のこと)などが入ってるよ。ここは誰でも読めるから、さっきも言ったとおりパスワードや個人情報を入れてはダメだよ。

署名(Signature)

3番目のパーツが署名で、これがJWTの「安全性の核心」なんだ。署名はサーバーだけが知ってる「秘密鍵」を使って作られるハッシュ値、つまり「改ざん検知用の特殊なチェックサム」だよ。

ハッシュとはつまり「同じデータからは必ず同じ値が生成されるけど、ちょっとでもデータが変わると全然違う値になる」という特徴を持つ計算のことだよ。だから、ペイロードを書き換えても署名が変わらなければ「あれ、データと署名が合わない、偽物だ!」とバレてしまう仕組みなんだ。これは封筒に封蝋(シール)を押すようなイメージで、一度開けると痕跡が残って「誰かに開けられた」とわかるのと同じだよ。

JWTを使ったログインの流れを追いかけよう

ステップ1:ログインリクエスト

まず、ユーザーがIDとパスワードを入力してログインボタンを押すと、その情報がサーバーに送られるよ。ここまでは普通のログインと同じだね。

ステップ2:サーバーがJWTを発行する

サーバーはIDとパスワードをチェックして、正しければJWTを作って返してくれるよ。このとき、ペイロードに「このユーザーはAさんで、権限はuserで、有効期限は1時間後」みたいな情報を入れてから、秘密鍵で署名して完成!これがユーザーに渡されるチケットになるんだ。

ステップ3:クライアントがJWTを保存する

もらったJWTをブラウザかアプリが保存しておくよ。よく使われるのは「ローカルストレージ(ブラウザ内のメモ帳みたいな場所)」か「Cookie(ブラウザに保存される小さなデータ)」だ。どちらにも一長一短があって、セキュリティの観点から議論されることも多いテーマなんだよ。

ステップ4:次のリクエストからJWTを送る

次にサーバーにアクセスするとき、HTTPリクエストの「Authorizationヘッダー」にJWTを入れて送るよ。ヘッダーとはつまり「リクエストに添付するメタ情報(データについての説明書き)」のことだ。こんな感じで送るよ:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

「Bearer」はつまり「これがトークンです」という宣言みたいなものだね。

ステップ5:サーバーが署名を検証する

サーバーはJWTを受け取ると、署名が正しいか確認して、有効期限が切れてないか確認して、OKなら「はい、この人はAさんです」とわかって処理を続けてくれるんだ。このとき、サーバーはデータベースを見に行かなくてもいいから、とっても高速に処理できるのも魅力だよ。

JWTのメリットとデメリットをセットで理解しよう

JWTの3つのメリット

JWTには大きく3つのメリットがあるよ。

  • サーバーがセッション情報を持たなくていい:昔ながらのセッション方式(つまりサーバー側で「誰がログイン中か」のリストを管理する方法)と違って、JWTはトークン自体に情報が入ってるから、サーバーはJWTを受け取るだけで誰かわかるんだ。これを「ステートレス(状態を持たない)」と言って、サーバーを増やしても同じJWTでどのサーバーでも認証できるよ。
  • 複数のサービスで使い回しやすい:GoogleのJWTをYouTubeでも使えるように、同じJWTを複数のサービスで使えるんだ。これをシングルサインオン(SSO)と言って、つまり「一回ログインしたら複数のサービスに自動でログインできる仕組み」のことだよ。
  • モバイルアプリとの相性が良い:スマホアプリはCookieが使いにくいけど、JWTならHTTPヘッダーに入れて送れるから、アプリの認証にとても向いてるんだ。

JWTの3つのデメリット

一方で、デメリットもあるから知っておこう。

  • トークンの無効化が難しい:一度発行したJWTは、有効期限が来るまで使えてしまう。もし「このユーザーをすぐにログアウトさせたい」という状況が起きても、JWTは有効期限までずっと使えてしまうんだ。これを解決するために「ブラックリスト」を持ったりするけど、そうするとステートレスの良さが薄れてしまうというジレンマがあるよ。
  • サイズが大きくなりやすい:JWTはペイロードに情報を入れすぎると、毎回のリクエストで大きなデータを送ることになるよ。特にモバイル回線では通信コストが上がる可能性があるんだ。
  • 盗まれたら悪用されるリスク:JWTが盗まれると、有効期限が切れるまで攻撃者がなりすましできてしまう。だから保存場所やHTTPS(通信の暗号化)をしっかり設定することがとても大切だよ。

JWTを安全に使うための注意点

有効期限は短めに設定しよう

JWTの有効期限は短めに設定するのがセキュリティの基本だよ。よくある設定は「アクセストークンは15分〜1時間、リフレッシュトークンは7〜30日」というパターン。アクセストークンとはつまり「実際の操作に使う短命なトークン」で、リフレッシュトークンとはつまり「アクセストークンを更新するための長命なトークン」のことだよ。

牛乳で例えると、アクセストークンはコンビニで買って今日使うための小さいパック(すぐ使い切る)で、リフレッシュトークンは冷蔵庫のストック(長く保管して必要なときに新しいパックと交換)みたいなイメージだよ。

必ずHTTPSを使おう

JWTをHTTPSなしで送ると、通信を傍受されてトークンを盗まれる可能性があるよ。HTTPSとはつまり「通信内容を暗号化して、第三者に盗み見られないようにする通信規格」のことだ。今どきのWebサービスはほぼ全部HTTPSを使ってるけど、自分でサービスを作るときは必ず設定しようね。

アルゴリズムの指定に注意しよう

JWTのヘッダーには署名アルゴリズムを指定するんだけど、「none」(署名なし)という値を受け入れてしまうと、攻撃者が署名なしのJWTを作って偽装できてしまうよ。これは実際に起きた有名な脆弱性で、つまり「セキュリティ上の穴」だよ。だからサーバー側で「このアルゴリズム以外は受け付けない」と明示的に指定することがとても大切なんだ。

センシティブな情報はペイロードに入れない

さっきも言ったけど、JWTのペイロードはBase64でデコードすれば誰でも読めるよ。だからパスワード・クレジットカード番号・マイナンバーなどの個人情報や秘密情報は絶対にペイロードに入れないようにしよう。JWTに入れていいのは「このユーザーのIDは何番で権限は何か」程度の最低限の情報だけにするのがベストプラクティス(つまり「みんなが認める一番良いやり方」)だよ。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

大人になってから「これ知らなかった…」と恥ずかしい思いをした経験から、このサイトを作りました。お金・仕事・社会のしくみって、学校で教えてくれないのに知らないと損することだらけ。むずかしい言葉を「あーそういうことか!」って思えるまでかみ砕いて説明するのが得意です。主に経済・法律・税金・ライフイベント周りの用語を毎日更新中。

目次