📖

【Web】Webアプリケーションの認証についてまとめてみた

2024/09/23に公開

JWT(JSON Web Token)認証

認証情報を含んだJSON形式のデータをHTTPヘッダで送信できるように他の形式へ変換(エンコード)したトークンで、署名を含んでいるために改ざん検知ができるのが特徴です。
JWTはOpenID ConnectのIDトークンの形式としても採用されています。トークン自体に認証情報が含まれていることで直接ユーザーを特定することができるため、トークンをデータベースに保存する必要がないのがメリット。サーバー側でユーザーのログイン状態を管理する必要がないというのは、RESTfulなAPIとの相性も良さそうです。

またトークン自体に有効期限を持たせることも可能。
JWT認証では、トークンが改ざんされていないかリクエストのたびに毎回検証が行われるため、JWTを返した正規のサイトからのリクエストであるということが推定されるため、安全性が高まります。

注意点として、JWTは「署名」されているものの、鍵を持っている人しか読めないように「暗号化」されているわけではありません(オプションで暗号化することも可能)。誰でも簡単にトークンから元の情報を複合することができるため、パスワードなどの機密情報をJWTに含めないように注意しなければいけません。

JWTの構造

JWTは、<ヘッダ>.<ペイロード>.<署名>といった構造を取ります。
以下のJWTトークンを見てみると、ドットで三つの文字列が一列につながっていると思います。

JWTトークン
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

ヘッダ(HEADER)

ヘッダには署名のアルゴリズムなどを記載します。
署名のアルゴリズムとトークンのタイプが記載されたJSONデータをエンコードすることによって、ヘッダ情報が生成されます。

ペイロード(PAYLOAD)

ペイロードはアプリケーション側で任意の値を埋め込むことができます。
こちらにユーザーの認証情報を埋め込んだりします。

署名(VERIFY SIGNATURE)

署名では、ヘッダで定義されたアルゴリズムを用いて作成された署名情報が用いられます。

以下のサイトでは、JWTトークンをデコード、またJWTトークンの生成をすることができます。
https://jwt.io/

OAuth

OAuthとは、複数のWebサービスを連携して動作させるために使われる仕組みです。通常、Webサービスを利用するためには、個別にユーザーIDとパスワードを入力してユーザーを認証する必要がありますが、OAuthを利用することで、IDやパスワードを入力することなく、アプリケーション間の連動ができるのです。

例えば、Instagramに投稿した写真を、Facebookでも同時に投稿したい場合を考えてみると、Instagramの設定画面で、Facebookの「リンク済み」アカウントを登録することによって、Instagramに投稿した写真が、Facebookにも同時に投稿されます。

このようにWebサービス間の連携の根幹を担っているのがOAuthなのです。

OAuth2.0

OAuth2.0は、ユーザーの認証情報を共有しなくても、ユーザーに変わって、合意されたアクセスを提供し、クライアントアプリがリソース日して時刻できるアクションを規制します。

具体的にOAuth1.0からどのような改善がされたのか。

  1. ブラウザではないアプリへの対応が改善
    スマホで使うアプリなどのブラウザ以外のアプリにも対応しやすくなりました。

  2. 署名の生成が不要になった
    署名の生成が不要になったため、アクセストークンの盗聴に強くなりました。

  3. 短命のアクセストークンとリフレッシュトークンの導入
    有効期限の短いトークンを導入することにより、同じトークンを長い期間使い回すといった盗聴の観点での懸念点が薄まりました。

OAuthは認証ではない

OAuthは認証のためのプロトコルではなく、認可のためのプロトコルです。
認証とは、相手が誰なのかを確認すること。
認可は、リソースアクセスの権限を与えること。
OAuthでは、一体誰なのかに関係なく、リソースアクセスを許可したいときに利用されるのです。

Basic認証

Basic認証は、管理する特定のWebページやファイルへのアクセス制限を行うシンプルなHTTP認証の一つです。

Basic認証では、ユーザー名とパスワードの組みをコロン":"でつなぎ、Base64でエンコードして送信します。
トークンはWebブラウザの内部に保存され、リクエストのたびにリクエストヘッダに書き込まれて自動送信されます。
そのためCSRF認証が必須となりますが、そもそもユーザー名やパスワードなどの機密情報が簡単に復号できてしまうため、インターネットに公開するWebアプリケーションの認証方式として採用することはできません。簡易的なサイトや社内で特定のメンバーとのみ共有する場合などで活用されます。

トークン認証

トークン認証は、ユーザーがユニークなアクセストークンと引き換えに本人確認を行う認証プロトコルです。JWT認証はトークン認証の一種です。

JWTにはユーザーの情報や、署名に関する情報が含まれていますが、トークン認証では他にも、ランダム生成やUUID/GUIDを使用したり、ハッシュ関数により、ログイン情報を暗号化することによってトークンを生成したりもします。

生成されたトークンは、ブラウザのローカルストレージやセッションストレージ、Cookieなどのクライアント側や、データベース、キャッシュなどのサーバー側に保存されます。

Cookie認証

Cookie認証は、Webブラウザで認証を行うことで、ユーザーが利用できる端末やブラウザを限定して不正利用を防ぐ仕組みです。
サーバー側のセッション(データベースやメモリキャッシュサーバなど)にユーザーのセッション情報(id=3のユーザーがログイン中、などといった情報)を保存し、セッション情報を特定するためのID(セッションID)をWebブラウザ側のCookieに保存して、その後はリクエストヘッダにセッションIDをセットして毎回送信することで、サーバー側でユーザーを特定してログイン状態を判定するという仕組みになっています。

すなわち、サーバー側の「セッション」でユーザーのログイン状態を管理していることになります。

参考

https://zenn.dev/mikakane/articles/tutorial_for_jwt

https://dev.classmethod.jp/articles/authentication-and-authorization/

https://note.com/shinya_matsui/n/n1df624cf36ba

https://ja.wikipedia.org/wiki/Basic認証

Discussion