1432
1238

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 5 years have passed since last update.

JSON Web Token の効用

Last updated at Posted at 2014-12-14

Note: JWT の仕様やそもそも論の話は触れません。どう使うか、何が出来るかしか書いていません。

JSON Web Token?

JSON Web Token とは、ざっくりいって署名の出来る JSON を含んだ URL Safe なトークンです。
署名とは、署名時に使った鍵を用いて、JSON が改ざんされていないかをチェック出来るようにすることです。
URL Safe とは、文字通り、URL に含めることの出来ない文字を含まないことです。

これだけだとよくわかりませんが、触り心地としては次のような性質があります。

  1. 発行者だけが、鍵を使ってトークンが正しいことを検証出来る。
  2. 暗号化ではないので、JSON の中身は誰でも見られる。
  • 仕様的には、暗号化のオプションもあります。
  1. しかしながら、JSON の変更は出来ない。(改ざんをすると、検証時に失敗するので。)
  2. 全体的には、なんか変更できない JSON だと受けとっておけばよいかと

使われかた

この性質のため、認証サーバなどによく使われます。簡易フローとしては、

  1. クライアントは認証サーバに認証情報(よくあるのは user_id, password)を渡し、トークンを請求する。
  2. 認証サーバは認証情報が正しいことを確認して、秘密鍵を使って署名された JWT を発行する。
  • この JWT は user_idexpiration_date を含む。
  1. クライアントはこの JWT を使って通常の API リクエストを行なう。
  2. サーバは、秘密鍵を使って JWT を検証し、user_id を JSON から取り出し、処理を行なう。

通常、このようなトークンを発行すると、user_id を書き換えるだけで全てのユーザにアクセス出来てしまう致命的なセキュリティホールを作ってしまいます。
expiration_date も同様で、これを書き換えるだけで無限に有効期限の切れないトークンが作れてしまいます。

しかし、JWT は「改ざん検証」が可能です。これを利用して、サーバでは検証が通らないトークンはすべて弾くようにします。そうすれば、事前にサーバが認めた user_idexpiration_date のみが通るようになります。

サーバは一度ユーザの認証情報を確認してからトークンを発行していますので、ここでの user_id は信頼でき、ログインしているものと扱うことができます。

サーバが署名した情報だから、改ざんされていない(=検証が通る)限りは信頼して使ってよいということですね。

この強力な署名の仕組みの為に、トークンに含む内容にセンシティブにならずに、標準化された方法で簡単にトークンを発行出来ることが特徴です。

実際、このような仕組みを使わずに、セキュアにトークンを発行することは大変です。
素直にやれば、トークンをランダム生成し、サーバサイドでトークンと user_id, expiration_date を紐づけてストアし、トークンを受け取るたびに毎回フェッチして user_id などを取り出す、という大仰な仕組みが必要になります。

トークンに、改ざんに対して安全に情報を保持させられることは、一見地味ですが強力な性質です。

ユースケース

JSON Web Token は様々な利用方法がありますので、色々見ると面白いと思います。

  • OAuth のトークンとして
    • Google の OAuth Token は JWT なので、Google API にトークン検証のリクエストをしなくてもトークンが検証できます。(公開鍵暗号を用いて署名していますので、クライアントには検証専用の鍵が配布されています。)
  • メール認証のトークンとして
    • scopeverify_email とした user_id 付きのトークンを発行
  • パスワード忘れメール送付時のトークンとして
    • scopereset_password とした user_id 付きのトークンを発行
  • サービスをまたいだ認証機構として
    • 自社のサービス間で鍵を共有することで、かんたんに独立した認証サービスを作ることができます。
  • 共有用URLとして
    • scope を工夫することでどこまで guest に権限を持たせるかを決めることもできます。たとえば、scope = view(album#56) などとして id = 56 の Album の閲覧のみが可能な URL を発行するなど。
    • ただし、URLがとんでもなく長くなるので短縮を噛ませるなど必須です。

使い勝手

JSON Web Token はライブラリがたくさんあります。

Objective-C もエンコード(発行)だけですが、ライブラリがあります。

インターフェースとしてはどの言語も、JSON と秘密鍵を渡したらよしなにしてくれるような感じです。お手軽。
何も考えなくて良いのが JWT の良い所。

# エンコード
JSON::JWT.new({foo: "bar"}).sign(key, algorithm)
# デコード
JSON::JWT.decode(jwt_string, key)
// エンコード
[JWT encodePayload:@{@"foo": @"bar"} withSecret:@"secret"];

Conclusion

  • JWT には実質改ざん不可能な情報を含めることが出来る。
    • この性質のため、認証サーバから返されるトークンに使われる。
  • JWT を上手く使うことで安全な通信 / 連携を実現出来る。
  • JWT を扱えるライブラリが沢山ある。
  • JWT は URL Safe なので、取り扱いが楽。
  • トークンはとりあえず JWT を使っておけばいいだろう、という安心感がある(私見)
  • 本文では触れませんでしたが、公開鍵暗号での署名であれば「署名用の鍵」と「検証用の鍵」を分けることが可能です。JWT発行サーバには署名用の鍵を持たせ、他のサーバには検証用の鍵を持たせることもできます。

References

1432
1238
2

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
1432
1238

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?