Rails 5 API で JWTを使った Token Based 認証機能を実装する 〜 事前準備 ~

What is JWT

JWT(「ジョット」と発音するようです)は JSON Web Tokenの略で、「JSONに電子署名をして、URL Safeな文字列にしたもの」です。JWTはJSONに電子署名をしたものですので、JSONの中身自体は読み出し可能です。しかし、電子署名がついているので内容の改ざんはできません。

JWT の構造

では、一体JWTとはどんな文字列なのか例を以下に示します。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0OTk2MTE0MzJ9.m_83YnBXsh2VYp4QSlPm1Hu4VWj3Sd8YYKSOKPH2FLk

JWTの文字列の中には2つの「ドット(ピリオド)」が含まれています。JWTはこの「ドット」を境に以下の3つのパートから構成されます。

ヘッダ(Header)

トークンのタイプ(JWT)と署名アルゴリズム(SHA256等)等のメタ情報を base64エンコードした文字列から構成されます。

ペイロード(Payload)

JSON本体に相当する情報をbase64エンコードした文字列です。

署名情報(Signature)

署名情報です。

上の方で「JSONの中身自体は読み出し可能」と書きましたが、この「中身」をみるにはペイロードを見ればいいのです。先ほど例を挙げたJWTだとペイロードは

eyJ1c2VyX2lkIjoxLCJleHAiOjE0OTk2MTE0MzJ9

です。試しにこのペイロードをデコードしてみましょう。

echo eyJ1c2VyX2lkIjoxLCJleHAiOjE0OTk2MTE0MzJ9 | base64 --decode

> {"user_id":1, "exp":1499611432}

これが、「JSONの中身」ですね。

JWTのユースケース

さて、ここまでJWTの基本的な性質を長々とみてきましたが、どういった用途に使えるでしょうか。答えのうちの1つは本稿のタイトルにもなっちゃっていますが…. Webの場合、セッションの代わりというか認証用のトークンとしてのユースケースがあります。他にはメール着信確認トークン(メールアドレスの登録時に確認メールを送り、そのメールに含まれるURLを踏ませる、というアレ)といったユースケースも考えられます。

Token Based 認証

少し唐突ですが、上記のうちJWTを認証用のトークンとして利用するケースを見てみます。

Token Based 認証の簡単な流れは

  1. クライアントは認証サーバに認証情報(user_id, password等)を送信し、トークンを請求する。
  2. 認証サーバは認証情報が正しいことを確認して、トークン を発行する。
  3. クライアントはこの トークン を使って API リクエストを行なう。
  4. サーバは トークンから必要情報を取り出し、処理を行なう。

という感じになります。フローは従来のCookieベースの認証と大きく変わりませんが、Cookieベースの認証はCookieヘッダを使い、Token Based 認証では Authorizationヘッダを使うところが異なります。

こういったトークンを(セキュリティ的な考慮なしに)発行すると、user_id を書き換えて任意のユーザになりすましたり、expiration_date を書き換えて有効期限を自由に操れたりといった致命的な欠陥を生み出してしまいます。

しかしながらJWTを認証トークンとして使えば、この欠点を署名を検証することで克服することができます。サーバは一度認証情報を確認してから署名していますので、検証が通る(= 改ざんされていない)限りは信頼して使って良いことになります。

トークンに「改ざんに対して安全に情報を保持させることができる」ということは非常に強力な性質なのです。

Token Based 認証のメリット

では、Token Based 認証のメリットはどういったところにあるでしょうか。他にもいろいろあると思いますが、下記はメリットと呼べるのではないでしょうか。

CSRF が発生しない

Cookieに依存していないので、CSRF脆弱性はなくなります。 (注意:トークンをCookieに保存したりする場合はCSRF脆弱性がのこります。)

ステートレス

Tokenは Self-Contain なのでサーバで状態を保持する必要がなくステートレスです。

クロスドメイン

Cookieはドメインを超えることはできませんが、Token Based 認証は Authorization ヘッダをつかってやりとりするので異なるドメインへユーザ情報を送信することが可能です。

おわりに

おおまかにではありますが、JWTとToken Based 認証についておさらいをしてみました。次回からは JWTを利用した認証を Rails5で簡単なAPIアプリを作成して確認してみることにしましょう。