1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

JWTの基本とJWSを使った認証を理解する

Posted at

この記事を書こうと思った経緯

仕事で携わっているプロダクトの認証機能にJWTを使用しているのですが
「認証の時に使う暗号化された文字列」
ぐらいにしかわかっていなかっていませんでした。

JWT、そして認証で使うJWSとJWTについてまとめてみました。

JWTを簡単にまとめると?

JWTはJson Web Tokenを略したものになります。

RFC(IETFという「インターネット関連の基準を決めている組織」によって取りまとめた基準を文書にしたもの)によると、JWTとは

HTTP AuthorizationヘッダーやURIクエリパラメーターなど、スペースに制約のある環境向けのコンパクトなクレーム表現形式です。

とあります。

「クレーム表現形式」というのはJWTの用語で、JSONのキーと値のペアのことです。
ここでは「JSONオブジェクト」と考えてください。

つまり、「スペースに制約のある環境向けのコンパクトなJSONオブジェクトの表現形式」ということです。

ちなみに、JWTの読み方はジェイダブリューティーではなく、ジョットですので覚えておきましょう。

JWTの形式

JWTを構成する形式は大きく2つです。

  1. JSONオブジェクトをURLに乗せられるようにエンコードする
  2. コンパクトになるように短いキー名が用意されている

...........これだけ??

と思ったあなた、

そうです、JWT自体はこれだけです。

1. URLに乗せられるようにエンコードする

URLには/+といった特定の文字は使えません。
そこで、Base64URLエンコードを行い、URLに使える文字に変換します。

元のJSONオブジェクト

{
  "sub": "1234567890",
  "iat": 1516239022,
  "email": "hogehoge+hugahuga@example.jp"
}

↓ 
Base64URLエンコードした文字列

eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyLCJlbWFpbCI6ImhvZ2Vob2dlK2h1Z2FodWdhQGV4YW1wbGUuanAifQ

+という文字がエンコードされ、URLに使える文字列になりました。

2. コンパクトになるように短いキー名が用意されている

JWTにはJSONオブジェクトのキーが短く表せるよう省略形が定義されています。

キー 意味 日本語
iss Issuer JWTの発行者
sub Subject ユーザの識別子などJWTの主体
aud audience JWTの受信者
exp expiration time JWTの有効期限
nbf Not Before JWTの有効開始日時
iat Issued At JWTの発行日時
jti JWT ID JWTの一意な識別子

実際に使うときには、このような表示形式になります。

{
  "iss": "io.exact.sample.jwt",
  "sub": "sample",
  "exp": 1670085336,
}

あれ、、、認証とか暗号化とかの話は出てこないの。。。。。?と思った方、その通りです。

JWT自体は認証や暗号化をしているわけではなく、あくまで表示形式のことなのです。

じゃあ認証に使っていたJWTって、一体なんだったの.....?
これについて述べていきたいと思います。

JWS

先ほどお伝えした通り、JWT自身には認証や暗号化はされていません。
Base64URLでエンコードされたものはデコードすれば元のJSONを知ることができます。
JWTではセキュリティに関しては考慮されていません。

そこで、JWTを使って認証するには JWS というものが使われます。

JWSとは JSON Web Signature の略で、「データの改竄(かいざん)を検知」することができます。

ここで注意するのは
改竄をできないようにするのではなく、
改竄したということを知ることができるということです。

「送信元が意図したとおりの形でデータが受け取り側に到達したかを確認する」手段としてデータ署名を使います。

ここからは公式サイトの画面を使って説明していきます。
スクリーンショット 2023-06-18 23.08.46.png

左側のEncodedのところに書かれた長い文字列が、エンコードされたJWS
右側のDecodedのところに書かれているのがJWT形式で書かれたJSONオブジェクトになります。

これを見て分かる通り、JWSは

  • Header(ヘッダー)
    • 署名に利用された鍵やアルゴリズム名などの情報
  • Payload(ペイロード)
    • 本文
    • ここにJWTが入っている
  • Verify Signature(シグニチャー)
    • 本文から作成した署名

の3部分から構成されており
それぞれをBase64URLでエンコードし、.(ドット)で繋いだもの
となっています。

ここで、「クレーム」に関連する用語について深掘りしていきましょう

クレームとは、RFCによると

対象について主張された情報の一部。クレームは、クレーム名とクレーム値で構成される名前と値のペアとして表されます。

と定められており、画像での
"iss": "sample.jwt""sub": "sample"はそれぞれクレームと呼ばれるということになります。

また
"iss""sub"をクレーム名、
"sample.jwt""sample"をクレーム値と呼びます。

さらに
クレームセットとというのは、以下のようにJWTによって伝えられたクレームを含むJSONオブジェクトを指します。

{
  "iss": "sample.jwt",
  "sub": "sample",
  "exp": 1670085336,
  "email": "sample@example.com"
}

....
さて、ペイロードのお話に戻すと、ペイロードにはJWTのクレームセットが入っています。

JWSの生成方法

生成手順は下記のとおりになります。
生成した1つの文字列となりますが、この文字列を生成する手順を「JWSコンパクトシリアライゼーション」と呼びます。

  1. ペイロードをBASE64URLエンコードする
  2. ヘッダーをBASE64URLエンコードする
  3. BASE64URL エンコードした1と2の結果を.(ドット)で繋ぐ
  4. 3の結果を暗号鍵とalgに指定された方式で署名(暗号化)し、その結果をさらにBASE64URLエンコードする
  5. 3(ヘッダー+ペイロード)と4(シグニチャ)の結果を.(ドット)で繋ぐ

つまり、3で生成されたものと、4で生成されたものを複合化した時に一致していないとおかしいということになり、異なる場合には改竄されたということになります。

JWSの検証方法

共通鍵方式(秘密鍵方式)を使った場合で考えていきます。

先ほどお伝えした通り、シグニチャーは復号化したものは、ヘッダーとペイロードを.(ドット)で繋いだものと全く同じになるはずです。
JWTの検証.drawio.png

まとめ

いかがだったでしょうか。

JWTは「HTTP AuthorizationヘッダーやURIクエリパラメーターなど、スペースに制約のある環境向けのコンパクトなクレーム表現形式」

JWSは「JWTをJWSコンパクトシリアライゼーションしたもの」

以下を押さえておけば混乱しないかと思います。

JWTに関する
JWE(Json Web Encrryption)やJWK(Json Web Key)などもあるので
そちらはまた今度まとめたいと思います。

参考文献

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?