Skip to content

Instantly share code, notes, and snippets.

@issm
Created July 8, 2016 11:55
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save issm/63889b931b8c658f23634070b64f8b23 to your computer and use it in GitHub Desktop.
Save issm/63889b931b8c658f23634070b64f8b23 to your computer and use it in GitHub Desktop.

元記事: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/

Stop using JWT for sessions

セッションとして JWT を使うのをやめよう

Update - June 19, 2016: A lot of people have been suggesting the same "solutions" to the problems below, but none of them are practical. I've published a new post with a slightly sarcastic flowchart - please have a look at it before suggesting a solution.

更新 - 2016-06-19: 多くの人がこの問題に対する「解決策」を下で議論しているが,そのいずれも現実的なものではない. ちょっとした皮肉を込めて 新しいエントリを起こした ので,議論する前に目を通してみてほしい.


Unfortunately, lately I've seen more and more people recommending to use JWT (JSON Web Tokens) for managing user sessions in their web applications. This is a terrible, terrible idea, and in this post, I'll explain why.

不運にも,私は最近,多くの人たちが Web アプリケーションにおけるユーザセッションの管理に JWT (JSON Web Tokens) を使うことを薦めているのを見てきた.これはぞっとする,ぞっとする考えであり,この投稿ではその理由を説明する.

Just to prevent any confusion, I'll define a few terms first:

  • Stateless JWT: A JWT token that contains the session data, encoded directly into the token.
  • Stateful JWT: A JWT token that contains just a reference or ID for the session. The session data is stored server-side.
  • Session token/cookie: A standard (optionally signed) session ID, like web frameworks have been using for a long time. The session data is stored server-side.

混乱を防ぐために,最初にいくつかの項目を定義しておく:

  • ステートレスな JWT: セッションデータを含んでいる JWT,直接エンコードされたトークンである.
  • ステートフルな JWT: セッションへの参照もしくは ID のみを含んでいる JWT.セッションデータはサーバ側で保持される.
  • セッショントークン/セッション cookie: 長期にわたり Web アプリケーションフレームワークが使っている標準的な (任意に署名された) セッション ID.セッションデータはサーバ側で保持される.

To be clear: This article does not argue that you should never use JWT - just that it isn't suitable as a session mechanism, and that it is dangerous to use it like that. Valid usecases do exist for them, in other areas. At the end of this article, I'll briefly go into those other usecases.

本記事は JWT を決して使うべきでないと言っているのではなく,セッションのメカニズムとしては不適であり,そのように利用することが危険であることを言っているだけ,ということを明確にしておきたい.それら (訳註: セッション管理?) に対する妥当なユースケースは他の領域に存在している.本記事の最後で,他のユースケースを簡単に説明する.

A note upfront

率直なメモ

A lot of people mistakenly try to compare "cookies vs. JWT". This comparison makes no sense at all, and it's comparing apples to oranges - cookies are a storage mechanism, whereas JWT tokens are cryptographically signed tokens.

多くの人が間違いにも "cookie vs. JWT" の比較しようとしている.この比較はまったくもって意味がない,リンゴとオレンジを比べている - cookie はストレージのメカニズムであり,一方 JWT は暗号で署名されたトークンである.

They aren't opposites - rather, they can be used either together or independently. The correct comparisons are "sessions vs. JWT" and "cookies vs. Local Storage".これらは対ではない - いっしょに使われるよりはむしろ,独立して使われる (訳註: ?).正しい比較は "セッション vs. JWT" であり "cookie vs. ローカルストレージ" である.

In this particular article, I will be comparing sessions to JWT tokens, and occasionally go into "cookies vs. Local Storage" as well where it makes sense to do so.

この記事では, セッションと JWT とを比較し,意味をなすようになったところで,ときどき "cookie vs. ローカルストレージ" についても触れる.

Claimed advantages of JWT

主張されている (訳註: ?) JWT の利点

When people recommend JWT, they usually claim one or more of the following benefits:

  • Easier to (horizontally) scale
  • Easier to use
  • More flexible
  • More secure
  • Built-in expiration functionality
  • No need to ask users for 'cookie consent'
  • Prevents CSRF
  • Works better on mobile
  • Works for users that block cookies

JWT を薦める人たちは,たいてい以下の利点 (のいつくか) を主張する:

  • (水平的に) スケールするのが容易である
  • 使うのが容易である
  • より柔軟である
  • より安全である
  • 'cookie の同意' をユーザに求める必要がない
  • CSRF を防ぐ
  • モバイルでより望ましく動作する
  • cookie をブロックしているユーザに対しても動作する

I'll address each of these claims - and why they are wrong or misleading - individually. Some of the explanations below may be a little vague; that's primarily because the claims themselves are vague. I'll happily update it to address more specific claims; you can find my contact details at the bottom of this article.

これらの主張 - そしてなぜ間違っているもしくは誤解である - ひとつひとつについてそれぞれ延べていく.以下の説明のうちいくつかは少々漠然としているかもしれないが,主としてそれらの主張自体が漠然としているからである.より明確な主張を述べるためによしなに update していく; コンタクトの詳細が本記事の下部にある.

Easier to (horizontally) scale

(水平的に) スケールするのが容易である

This is the only claim in the list that is technically somewhat true, but only if you are using stateless JWT tokens. The reality, however, is that almost nobody actually needs this kind of scalability - there are many easier ways to scale up, and unless you are operating at the size of Reddit, you will not need 'stateless sessions'.

これは先のリストにおいてだいたいそのとおりである唯一の主張であるが,ステートレスな JWT を使っている場合に限られる.

しかし現実には,その種のスケーラビリティはたいていはほんとうに必要ないのである - Reddit 規模のサイズを操作するのでなければ,スケールアップするためのより容易な手段があり,'ステートレスなセッション' は不要になるだろう.

Some examples of scaling stateful sessions:

  1. Once you run multiple backend processes on a server: A Redis daemon (on that server) for session storage.
  2. Once you run on multiple servers: A dedicated server running Redis just for session storage.
  3. Once you run on multiple servers, in multiple clusters: Sticky sessions.

ステートフルなセッションをスケールするいくつかの例:

  1. 単一サーバで複数のプロセスで実行している場合: セッションストレージのための (そのサーバ上の) Redis デーモン
  2. 複数サーバで実行している場合: セッションストレージのためだけの Redis が動いている専用サーバ
  3. 複数クラスタの中,複数サーバで実行している場合: sticky なセッション

These are all scenarios that are well-supported by existing software. Your application is very unlikely to ever go beyond the second step.

これらはすべて既存のソフトウェアに十分にサポートされているというシナリオがある.あなたのアプリケーションが第二の手段より優れていることはまずありそうにない.

Perhaps you're thinking that you should "future-proof" your application, in case you do ever scale up beyond that. In practice, however, it's fairly trivial to replace the session mechanism at a later point, with the only cost being logging out every user once, when you make the transition. It's just not worth it to implement JWT upfront, especially considering the downsides that I'll get to later.

あなたのアプリケーションをスケールアップを行うような場合,おそらく "future-proof" すべきだとお考えだろう.

しかし実際問題として,後にセッションのメカニズムを入れ替えることは,移行する際にユーザごとに一度ログアウトするだけのコストをとるだけで,まったく取るに足らないことである.

Easier to use

使うのが容易である

They really aren't. You will have to deal with session management yourself, on both the client and the server side, whereas standard session cookies just work, out of the box. JWT isn't easier in any way.

そうではない.クライアント側・サーバ側の両方でセッション管理を自分で処理しなければならないことから,標準的なセッション cookie に限り箱の外で (訳註: ?) 動作する. JWT は決して容易ではない.

More flexible

より柔軟である

I have yet to see somebody actually explain how JWT is more flexible. Almost every major session implementation lets you store arbitrary data for the session anyway, and this is no different from how JWT works. As far as I can tell, this is just used as a buzzword. If you disagree, feel free to contact me with examples.

どのように JWT がより柔軟であるかを誰かが説明するのを実際に見たことがない.たいていのメジャーどころのセッション実装は,どのみちセッションのため任意のデータを保持させ,これは JWT がどのように動作するかということと違いがない.私が伝えられる限りでは,これはバズワードとして使われているだけである.これに意義があれば,反例を持って気軽にコンタクトしてきてほしい.

More secure

より安全である

A lot of people think that JWT tokens are "more secure" because they use cryptography. While signed cookies are more secure than unsigned cookies, this is in no way unique to JWT, and good session implementations use signed cookies as well.

多くの人が JWT は暗号化を利用しているため "より安全である" と考えている.署名入り cookie は署名のない cookie よりも安全であり,これは決して JWT 固有のことではない.

"It uses cryptography" doesn't magically make something more secure either; it must serve a specific purpose, and be an effective solution for that specific purpose. Incorrectly used cryptography can, in fact, make something less secure.

"暗号化を利用する" こともまた,魔法のようにより安全にしてくれるわけではない.それは特定の目的を果たさなければならず,その特定の目的に対する効果的な解決策である.不正確に利用される暗号化は,事実,安全性を劣化させる.

Another explanation of the "more secure" argument that I hear a lot, is that "they are not sent as a cookie". This makes absolutely no sense - a cookie is just a HTTP header, and there's nothing insecure about using cookies. In fact, cookies are especially well-protected against eg. malicious client-side code, something I'll get into later.

私が多く耳にする "より安全である" ことの議論のもうひとつの説明は,"それらは cookie として送信されていない" である.このことはまったく無意味である - cookie はただの HTTP ヘッダであり,cookie 利用についての不安はまったくない.事実 cookie は,例えば後に取得する悪意のあるクライアント側のコードや何か,に対してとりわけ十分に保護されている.

If you are concerned about somebody intercepting your session cookie, you should just be using TLS instead - any kind of session implementation will be interceptable if you don't use TLS, including JWT.

もし誰かがセッション cookie を傍受するのが心配であれば,代わりに TLS を使うべきである - TLS を使わなければ,JWT も含めたいくらかのセッション実装は傍受されるだろう.

No need to ask users for 'cookie consent'

'cookie の同意' をユーザに求める必要がない

Completely wrong. There's no such thing as a "cookie law" - the various laws concerning cookies actually cover any kind of persistent identifier that isn't strictly necessary for the functioning of the service. Any session mechanism you can think of will be covered by this.

完全に間違いである."cookie の法則?" のようなものはない - cookie を懸念するいろいろな法則は,実際にはあらゆる種類の,サービスが機能するために厳密には不可欠ではない持続的識別子を対象とする.(訳註: わけわからない訳)

In a nutshell:

  • If you are using a session or token for functional purposes (eg. keeping a user logged in), then you don't need to ask for user consent, regardless of how you store that session.
  • If you are using a session or token for other purposes (eg. analytics or tracking), then you do need to ask for user consent, regardless of how you store that session.

つまり:

  • セッションもしくはトークンを機能的な目的 (例えば,ログイン状態を保つ) のために使うのならば,そのセッションをどのように保持するのかにかかわらず,ユーザの同意を求める必要は_ない_.
  • セッションもしくはトークンを他の目的 (例えば,分析やトラッキング) のために使うのならば,そのセッションをどのように保持するかにかかわらず,ユーザの同意を求める必要が_ある_.

Prevents CSRF

CSRF を防ぐ

It doesn't, really. There are roughly two ways to store a JWT:

  • In a cookie: Now you are still vulnerable to CSRF attacks, and still need protection against it.
  • Elsewhere, eg. Local Storage: Now you are not vulnerable to CSRF attacks, but your application or site now requires JavaScript to work, and you've just made yourself vulnerable to an entirely different, potentially worse class of vulnerabilities. More about this below.

防がない,本当に.JWT を記憶するためのだいたい 2つの手段がある:

  • Cookie にて: CSRF 攻撃に対して脆弱であり,それに対する保護が必要である.
  • そうでない場合,例えば,Local Storage: CSRF 攻撃に対しては脆弱でないが,アプリケーションまたはサイトで JavaScript が動作できる必要があり,完全に異なるもの,潜在的にもっとひどいクラスの脆弱性,に対して脆弱になるように自分でするだけである.このことについては以下.

The only correct CSRF mitigation is a CSRF token. The session mechanism is not relevant here.

CSRF を軽減する正しい唯一のものは,CSRF トークンである.セッションメカニズムはここでは適切でない.

Works better on mobile

モバイルでより望ましく動作する

Nonsense. Every mobile browser still in use supports cookies, and thus sessions. The same goes for every major mobile development framework, and any serious HTTP library. This is just not a problem at all.

Works for users that block cookies

cookie をブロックしているユーザに対しても動作する

Unlikely. Users don't just block cookies, they typically block all means of persistence. That includes Local Storage, and any other storage mechanism that would allow you to persist a session (with or without using JWT). Whether you use JWT simply doesn't matter here, it's an entirely separate problem - and trying to get authentication to work without cookies is a bit of a lost cause.

On top of that, users that block all cookies typically understand that this will break authentication functionality for them, and individually unblock cookies for sites where they care about this. It's simply not a problem that you, as a web developer, need to be solving; a much better solution is to explain to your users why your site requires cookies to work.

The drawbacks

(訳註: JWT の?) 欠点

Now that I've covered all the common claims and why they're wrong, you might think "oh, that's not a big deal, it still doesn't matter that I use JWT even if it doesn't help me", and you'd be wrong. There are quite a few downsides to using JWT as a session mechanism, several of them being serious security issues.

They take up more space

より大きなスペースを占める

JWT tokens are not exactly small. Especially when using stateless JWT tokens, where all the data is encoded directly into the token, you will quickly exceed the size limit of a cookie or URL. You might decide to store them in Local Storage instead - however...

They are less secure

安全性に劣る

When storing your JWT in a cookie, it's no different from any other session identifier. But when you're storing your JWT elsewhere, you are now vulnerable to a new class of attacks, described in this article (specifically, the "Storing sessions" section):

We pick up where we left off: back at local storage, an awesome HTML5 addition that adds a key/value store to browsers and cookies. So should we store JWTs in local storage? It might make sense given the size that these tokens can reach. Cookies typically top out somewhere around 4k of storage. For a large-sized token, a cookie might be out of the question and local storage would be the obvious solution. However, local storage doesn’t provide any of the same security mechanisms that cookies do.

Local storage, unlike cookies, doesn’t send the contents of your data store with every single request. The only way to retrieve data out of local storage is by using JavaScript, which means any attacker supplied JavaScript that passes the Content Security Policy can access and exfiltrate it. Not only that, but JavaScript also doesn’t care or track whether or not the data is sent over HTTPS. As far as JavaScript is concerned, it’s just data and the browser will operate on it like it would any other data.

After all the trouble those engineers went through to make sure nobody is going to make off with our cookie jar, here we are trying to ignore all the fancy tricks they’ve given us. That seems a little backwards to me.

Simply put, using cookies is not optional, regardless of whether you use JWT or not.

You cannot invalidate individual JWT tokens

個別の JWT を無効化できない

And there are more security problems. Unlike sessions - which can be invalidated by the server whenever it feels like it - individual stateless JWT tokens cannot be invalidated. By design, they will be valid until they expire, no matter what happens. This means that you cannot, for example, invalidate the session of an attacker after detecting a compromise. You also cannot invalidate old sessions when a user changes their password.

You are essentially powerless, and cannot 'kill' a session without building complex (and stateful!) infrastructure to explicitly detect and reject them, defeating the entire point of using stateless JWT tokens to begin with.

Data goes stale

データが新鮮でなくなっていく

Somewhat related to this issue, and yet another potential security issue. Like in a cache, the data in a stateless token will eventually 'go stale', and no longer reflect the latest version of the data in your database.

この問題にいくらか関連した,そしてもうひとつの潜在的なセキュリティの問題がある.キャッシュでのような,ステートレスなトークンの中のデータは,ゆくゆくは '新鮮でなくなり',もはやデータベースにある最新版のデータを反映していない.

This can mean that a token contains some outdated information like an old website URL that somebody changed in their profile - but more seriously, it can also mean somebody has a token with a role of admin, even though you've just revoked their admin role. Because you can't invalidate tokens either, there's no way for you to remove their administrator access, short of shutting down the entire system.

(訳註: この文わからない) このことは,誰かがプロフィールを変更した? 古いウェブサイトの URL のような古い情報を含むトークンは, ,ということを意味し得る.

しかしより深刻に,たとえその管理者ロールを無効にされたとしても,管理者ロールのついたトークンを持つ誰かが存在し得ることも意味する.

Implementations are less battle-tested or non-existent

実装が battle-tested に劣る,もしくは存在しない

You might think that all these issues are just with stateless JWT tokens, and you'd be mostly right. However, using a stateful token is basically equivalent to a regular session cookie... but without the battle-tested implementations.

これらの問題すべては単にステートレスな JWT を用いる際に考えるのがよく,ほぼ正しい.しかしながら,ステートフルなトークンを使うことはいつものセッション Cookie と基本的に同等である... しかし battle-tested な実装を除いて.

Existing session implementations (eg. express-session for Express) have been running in production for many, many years, and their security has been improved a lot because of that. You don't get those benefits when using JWT tokens as makeshift session cookies - you will either have to roll your own implementation (and most likely introduce vulnerabilities in the process), or use a third-party implementation that hasn't seen much real-world use.

既存の

Conclusion

結論

Stateless JWT tokens cannot be invalidated or updated, and will introduce either size issues or security issues depending on where you store them. Stateful JWT tokens are functionally the same as session cookies, but without the battle-tested and well-reviewed implementations or client support.

ステートレス な JWT は無効化もしくは更新させられず,それらを記憶する先に依存する,サイズの問題かセキュリティの問題を招く.ステートフルな JWT は,機能的にセッション Cookie と同じであるが,battle-tested かつよく検討された実装・client support を除く.

Unless you work on a Reddit-scale application, there's no reason to be using JWT tokens as a session mechanism. Just use sessions.

Reddit 規模のアプリケーションを動作させるのでなければ,セッションメカニズムとして JWT を使う理由はない.

So... what is JWT good for, then?

では... JWT は何に対して有効なのか?

At the start of this article, I said that there are good usecases for JWT, but that they're just not suitable as a session mechanism. This still holds true; the usecases where JWT is particularly effective are typically usecases where they are used as a single-use authorization token.

この記事の最初で,JWT にとって有効なユースケースがあることを述べたが,それらはセッションメカニズムとしては適切ではない.このことはまだ真実である; JWT が特に効果的なユースケースは,単一利用の認可トークンとして用いられる典型的なものである.

From the JSON Web Token specification:

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. [...] enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

JSON Web Token の仕様より:

JWON Web Token (JWT) はコンパクトであり,2つのパーティ間で転送されるクレームを表現する意味で URL-safe である.[...] クレームを有効にすることは,デジタル方式で署名される,もしくは,Message Authentication Code (MAC) と/もしくは暗号化で完全に保護される.

In this context, "claim" can be something like a 'command', a one-time authorization, or basically any other scenario that you can word as:

Hello Server B, Server A told me that I could <claim goes here>, and here's the (cryptographic) proof.

この文脈では,"クレーム" は 'コマンド',ワンタイム認可,のような何かであり,もしくは次のように言い表せる基本的に他の筋書きである:

こんにちはサーバ B,サーバ A は <claim goes here> と教えてくれた,そして (暗号化の) 証拠? がここにある.

For example, you might run a file-hosting service where the user has to authenticate to download their files, but the files themselves are served by a separate, stateless "download server". In this case, you might want to have your application server (Server A) issue single-use "download tokens", that the client can then use to download the file from a download server (Server B).

例えば,ユーザがファイルをダウンロードを行うために認証しなければならないファイルホスティング・サービスを実行するかもしれないが,ファイルそれら自体はステートレスな "ダウンロードサーバ" のように分離されて提供される.この場合,アプケーションサーバ (サーバ A) が,クライアントがダウンロードサーバ (サーバ B) からファイルをダウンロードするのに利用することができる,使い捨ての "ダウンロードトークン" を発行させたいだろう.

When using JWT in this manner, there are a few specific properties:

  • The tokens are short-lived. They only need to be valid for a few minutes, to allow a client to initiate the download.
  • The token is only expected to be used once. The application server would issue a new token for every download, so any one token is just used to request a file once, and then thrown away. There's no persistent state, at all.
  • The application server still uses sessions. It's just the download server that uses tokens to authorize individual downloads, because it doesn't need persistent state.

このやり方において JWT を使うとき,いつくかの具体的な特性がある:

  • トークンは短命である. クライアントがダウンロードを開始するのを許可するための数分間妥当であることが必要なだけである.
  • トークンは一度しか使われないことが期待される. アプリケーションサーバはダウンロードごとに新しいトークンを発行するだろう,そしてどの 1トークンも 1つのファイルを一度要求するだけであり,その後破棄される.持続する状態は,まったくない.
  • アプリケーションサーバはセッションを利用する. 各ダウンロードを認可するためにトークンを利用するダウンロードサーバだけであるり,そのため持続する状態は不要である.

As you can see here, it's completely reasonable to combine sessions and JWT tokens - they each have their own purpose, and sometimes you need both. Just don't use JWT for persistent, long-lived data.

ここでお分かりのように,セッションと JWT をいっしょにするのはまったく筋が通っている - それぞれ特有の目的があり,ときにはその両方を必要とする.JWT を持続する,長命なデータ,として利用してはいけないだけである.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment