JWTについてノンプログラマー向けにまとめてみた〜Zoom APIに出てくるJWTって何かわかりますか?〜

zoom dev console 雑記
この記事は約8分で読めます。

さて、スタートからよくわからないフレーズがタイトルに入ってますね。

やっとOAuthが市民権を得た(得てない?)気がしているノンプログラマー界隈ですが、JWTと言うものに接する機会がすぐそこに来ていそうです。

今回の記事の発端はZoom APIを使ってみたところに始まります。

Advertisements

物語の始まり

ある日の自分
ある日の自分

あぁZoom API使ってやればこれできるかなぁ
とりあえず触ったことないしDev consoleみてみるかぁ

ぽちっ

zoom API管理画面
ある日の自分
ある日の自分

おぉJWT書いてあるやん!ちょいテンションあがるw

どうでもいい書き出しではありますが、JWTと言うフレーズに反応してしまった自分がいたので、テンションのまま記事起こしw

JWTって何?

JWTとはJSON Web Tokenの略で、”ジョット”と呼びます。

JWTでなんでジョットやねん、読めへんやん、って方に悲報です。この読み方は実はRFCに規定されていますw

The suggested pronunciation of JWT is the same as the English word “jot”.

JWT とは、JSON 形式で表現されたクレーム (claim) の集合を、JWS もしくは JWE に埋め込んだものです。JWS(JSON Web Signature)は署名付きのJWT、JWE(JSON Web Encryption)は暗号化されたJWTって感じです。

なので、JWTは基本的にはクレームの集合を、JSON形式、つまりkey_value形式で保存しているものです。

(追記)JWTのクレームって何?

さて、急にクレームの集合なんて出てきてわかりにくいよ、ってご指摘いただいたので、クレームって何か追記してみます。

クレームに関してはJWTと言うか、OIDCなどで定義されている要素のままなので、OAuthに触れるといつも出てきて、当たり前になってしまうのですが、最初は用語の定義がわからないケースが一般的ですよね。

と言うことで、OIDCのJWTページから定義を引っ張ってきました。

クレーム

 ある主体に関するひとまとまりの情報。クレームはクレーム名とクレーム値から構成される名前と値のペアで表現される

クレーム名

 クレーム表現の中の名前の部分。クレーム名は常に文字列である。

クレーム値

 クレーム表現の中の値の部分。クレーム値は任意のJSON値であり得る  

https://openid-foundation-japan.github.io/draft-ietf-oauth-json-web-token-11.ja.html#Claims

要は、key_valueペアになった情報の集まりって感じです。わかりやすいところだと、(厳密には定義は違いますが)、urlにひっつけるクエリパラメータとかもクレームみたいな役割ですよね。

JWTってどんな形式になってるの?

ZoomのJWT一発目にエラー起こしてしまったので、ちょっと別のところからサンプル引っ張ってきました。

実際のJWTは以下のようなやつです。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

引用元:https://techblog.yahoo.co.jp/advent-calendar-2017/jwt/

よくわかりますねぇ。。。。ってわけないっすよねw これだけみてもJWSだってこと以外私もわかりませんw

ちょっとみやすくしてみます。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

JWTはカンマ区切りでそれぞれの文字列に意味を有していますので、カンマ毎に改行入れてみました。

JWTはカンマで区切られていて、各ブロックがそれぞれ別の要素となっている

JWTの要素はそれぞれ何?

それでは先ほど改行を入れた、JWTがそれぞれどんな要素を有しているのか確認してみましょう。yahooさんのブログにあったのが、JWSだったので以下のようになります。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9   #ここはヘッダー
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9 #ここはペイロード
.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ  #ここは署名

JWEの場合、もっとめんどくなりますが、まぁなかなかJWEを普段目にする機会はないので。。気になる方は、以下のブログみてみてください。

IDトークンが分かれば OpenID Connect が分かる - Qiita
はじめに 「解説記事を幾つも読んだけど OpenID Connect を理解できた気がしない」― この文書は、そういう悩みを抱えたエンジニアの方々に向けた OpenID Connect 解説文書です。概念的・抽象的な話を避け、...

JWT(正確にはJWS)は、ヘッダー・ペイロード・署名がカンマ区切りで含まれている

JWTをデコードしてみよう

JWTはbase64でエンコードされているので、簡単に誰でもデコード可能です。

pythonでやっていますので、pythonのbase64モジュールを利用します。

import base64

#yahooサンプル
jwt_header = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
decoded = base64.b64decode(jwt_header)
print(decoded)

jwt_payload = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9"
decoded2 = base64.b64decode(jwt_payload)
print(decoded2)

結果が以下の感じ

b'{"alg":"HS256","typ":"JWT"}' #ヘッダー
b'{"sub":"1234567890","name":"John Doe","admin":true}' #ペイロード

サンプルのヘッダー要素は?

ヘッダーには基本以下の2つの要素が含まれています。

param説明
alg署名に利用されるアルゴリズム
typJWS自身のメディアタイプ

どんなデータで、署名がどんなアルゴリズムによっているかが、書いてあります。署名系のアルゴリズムは山ほどあって、これだけでも私には深淵すぎて手を出せませんw

ちなみに、今回紹介した要素以外にも予約語は色々ありますので、気になる方はぐぐるかRFC読んでもらうのがいいかと思います。

サンプルのペイロード要素は?

ペイロードには3つの要素が含まれていました。

param説明
subSubject クレーム。ユーザーの一意識別子のこと
namenameクレーム。フルネームを表す
admin独自クレームかな?

subとnameクレームは予約語です。adminはあったかなぁ調べてないからわかんないw

サンプルの署名要素は?

署名はシンプルにデコードするだけではダメで、algで指定されたアルゴリズムに基づいて検証しなきゃいけません。自分でやるのめんどかったので、jwt.io(auth0さんがやってるやつ)でさくっとやってみました。

さて、長いこと前置き説明をしてきましたが、やっと各要素の雑な説明が終わったので、本題のZoom APIのJWTをみていきます。

Zoom APIのJWTをみていこう

全部乗っけるのは流石に暴挙なんで、ヘッダーとペイロードそれぞれの結果だけ乗っけていきます。

Zoom API JWT ヘッダー要素

ヘッダーをデコードすると以下の要素が含まれています。yahooさんのサンプルと同じなので、説明は省略しますね。

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

Zoom API JWT ペイロード要素

b'{"aud":null,"iss":"yc5foe_YS56jpjur4IwaRw","exp":1594176959,"iat":1594171559}'

先ほどyahooさんのサンプルでは含まれていなかった要素が含まれていますね、まぁ実際に利用するJWTなんでそりゃそうなんですがw

ちょっとだけ説明。

param説明
audaudクレーム。audienceのこと。JWT が、誰を対象として発行されたのかを示すもの。要はクライアントアプリケーションを表すもの。
ississクレーム。issuerのこと。JWTが誰によって発行されたか、要は発行者を特定するもの。
expexpクレーム。expiration timeのこと。JWTが失効する日時を表す
iatiatクレーム。issued atの略。JWTが発行された日時を表す

Zoom API JWTペイロードをデコードする際の注意点

ペイロード部分をシンプルにデコードしようとすると、以下のようなエラーが表示されます。

binascii.Error: Incorrect padding

パディングが違うと。base64は4文字区切りでデコードしていくので、綺麗に4文字単位にならないようにZoom API JWTのペイロード部分は作られてますね。

と言うことで、以下のようにしてやってみてください。

jwt_payload_zoom = "payload部分"
jwt_payload_zoom=base64.urlsafe_b64decode(jwt_payload_zoom + '=' * (-len(jwt_payload_zoom) % 4))

ここら辺のエラー解説は暇ができたら、ちゃんと記事にします。今回はこれでご勘弁を。

まとめ

JWTあるやーん、ってテンションだけで書き起こしてしまいました。

ノンプロ界隈でもOAuthが市民権を得てきたと勝手に思っており、その元となるJWTの概念も広まっていくと。。。全く思えませんがw

まぁどなたかノンプロで好きな方がいたら興味持ってもらえればいいなと思いました。

ちなみに、このJWTってクライアント認証と呼ばれる領域でも実用されていたりしますよ。

コメント