Skip to main content

JWTを扱う際のセキュリティに関するベストプラクティス3選

著者
feature jwt security

2023年12月18日

0 分で読めます
Top 3 JWT Security Best Practices for Your Apps

現代のWeb開発では、JSON Web Token(JWT)は、関係者間で情報を安全にやり取りする一般的な方法となっています。JWTは認証や認可に使われ、ユーザー情報の保存にもよく利用されます。しかし、JWTの利用が広がるにつれて、開発者が認識しておくべきセキュリティリスクも生じています。

開発者には、アプリケーションの安全性を確保し、ユーザーデータを保護する責任があります。このブログ記事では、JWTを扱う際のセキュリティに関するベストプラクティスを3つ紹介します。Pythonを使った実践例とともに、Snykがアプリケーションのセキュリティ脆弱性の特定と修正にどのように役立つかを解説します。

この記事を読み終える頃には、アプリケーションでJWTを安全に扱う方法や、コードの安全性を確保するためにSnykのようなツールを使う重要性への理解が深まっているはずです。それでは始めましょう。

ベストプラクティス1:JWTを秘密に保つ

JWTは、現代のWebアプリケーションで認証や認可に広く使われています。しかし、適切に扱わなければ、アプリケーションに重大なセキュリティリスクをもたらす可能性があります。このセクションでは、JWTを秘密に保つことの重要性と、その方法を説明します。

JWTを秘密に保つことが重要な理由

JWTは本質的に、ユーザーに関する情報を含む署名付きのJSONオブジェクトです。この情報には、ユーザーID、ロール、権限などの機密データが含まれる場合があります。攻撃者がJWTを入手すると、それを使ってユーザーになりすまし、アプリケーションに不正アクセスできてしまいます。

そのため、JWTを秘密に保ち、許可された関係者だけがアクセスできるようにすることが不可欠です。JWTの秘匿性について考えるときは、従来のWebアプリケーションにおけるセッションCookieを想像してみてください。攻撃者にCookieを盗まれれば、簡単になりすまされ、大きな被害を受けるおそれがあります。

JWTを秘密に保つ方法

JWTを秘密に保つための最初のステップは、ネットワーク経由で安全に送信されるようにすることです。クライアントとサーバー間のすべての通信にHTTPSを使用すれば実現できます。

2つ目のステップは、クライアント側でJWTを安全に保存することです。その方法の1つは、Cookieをクライアントに送信するときにHttpOnlyフラグとSecureフラグを使用することです。HttpOnlyフラグはクライアント側のスクリプトからCookieにアクセスできないようにし、SecureフラグはCookieがHTTPS経由でのみ送信されるようにします。

JWTを安全に保存するもう1つの方法は、sessionStorageやlocalStorageなどのブラウザーのストレージ機能を使うことです。これらの機能を使うと、他のドメインからアクセスできないデータをブラウザー内に保存できます。ただし、慎重に扱う必要があります。JWTをsessionStorageまたはlocalStorageに保存すると、JavaScriptコードからアクセスできるため、Webサイトを注意深く評価し、攻撃者によるJWTの窃取につながる可能性のあるクロスサイトスクリプティング(XSS)攻撃に対して脆弱でないことを確認してください。

最後に、サーバー側でJWTが適切に検証されるようにすることが不可欠です。これには、署名の確認とトークンの内容の検証が含まれます。

JWTを秘密に保つうえでのセキュリティ問題をSnykで検出する実践例

Snykは、JWTに関連するセキュリティ問題の特定に役立つ開発者向けセキュリティツールです。たとえば、アプリケーションで脆弱な暗号化アルゴリズムが使われていないか、Cookieをクライアントに送信する際にHttpOnlyフラグやSecureフラグが使われているかを検出できます。

Pythonのコード例を見てみましょう。

from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, jwt_required, create_access_token

app = Flask(__name__)

app.config['JWT_SECRET_KEY'] = 'super-secret'  # Keep your secret key safe and make sure it’s unique!
jwt = JWTManager(app)

@app.route('/login', methods=['POST'])
def login():
    username = request.json.get('username')
    password = request.json.get('password')

    # Check if the username and password are valid
    # ...

    # If the user is authenticated, create a JWT
    access_token = create_access_token(identity=username)

    return jsonify({'access_token': access_token}), 200

@app.route('/protected', methods=['GET'])
@jwt_required
def protected():
    return jsonify({'message': 'You are authorized!'}), 200

if __name__ == '__main__':
    app.run()

この例では、Flask-JWT-Extendedライブラリを使ってJWTを作成し、検証しています。Snykを使えば、脆弱な暗号化アルゴリズムが使われていないか、サーバー側でJWTが適切に検証されているかを確認できます。

Snykのようなツールを使うことで、アプリケーションの安全性を確保し、JWTを秘密に保つことができます。

ベストプラクティス2:JWTを検証する

前のセクションで説明したとおり、JWTは認証や認可に使われるため、侵害されるとセキュリティ侵害につながる可能性があります。そのため、JWTを信頼する前に検証することが不可欠です。

JWTの検証が重要な理由

JWTを検証することで、受信したリクエストが認証済みかつ認可されたユーザーからのものであることを確認できます。また、トークンが期限切れになっていないこと、改ざんされていないこと、発行者によって署名されていることも確認できます。JWTを正しく検証しないと、不正アクセスやデータ侵害などのセキュリティ脆弱性につながる可能性があります。

JWTを検証する方法

JWTを検証するには、次の手順を実行します。

  1. JWTを解析し、ヘッダー、ペイロード、署名を抽出する。

  2. 秘密鍵または公開鍵を使って署名を検証する。

  3. 有効期限(exp)と有効開始時刻(nbf)のクレームを確認し、JWTが有効であることを確かめる。

  4. 発行者(iss)のクレームを検証し、信頼できる関係者がJWTを発行したことを確かめる。

  5. オーディエンス(aud)のクレームを検証し、JWTが正しい受信者を対象としていることを確かめる。

Pythonには、JWT標準の実装であるPyJWTなど、JWTの検証に使えるライブラリがいくつかあります。以下は、PyJWTを使ってJWTを検証する例です。

import jwt

token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

try:
    decoded_token = jwt.decode(token, 'secret', algorithms=['HS256'], options={"verify_exp": True, "verify_iss": True, "verify_aud": True})
    print(decoded_token)
except jwt.ExpiredSignatureError:
    print("Token has expired")
except jwt.InvalidIssuerError:
    print("Invalid issuer")
except jwt.InvalidAudienceError:
    print("Invalid audience")
except jwt.InvalidTokenError:
    print("Invalid token")

上の例では、jwt.decode()メソッドを使ってトークンをデコードし、検証しています。algorithmsパラメーターは、署名の検証に使うアルゴリズムを指定します。optionsパラメーターは、有効期限、発行者、オーディエンスの検証など、実行する追加チェックを指定します。

JWTの検証に関するセキュリティ問題をSnykで検出する実践例

Snykは、JWTの検証に関するセキュリティ問題を検出できる包括的なセキュリティスキャンツールを提供します。たとえば、安全でないアルゴリズムの使用や、発行者またはオーディエンスのクレーム未検証といった、安全でないJWT検証の実装をコードベースから検出できます。また、JWTの検証に使われるサードパーティ製ライブラリの脆弱性も検出できます。

Snykを使えば、開発者はJWTの検証に関連するセキュリティ脆弱性がコードベースに存在しないことを確認できます。Snykを始めるには、開発者は無料アカウントに登録し、開発ワークフローに組み込むことができます。

ベストプラクティス3:JWTに有効期限を設定する

JWTは、関係者間で情報を安全にやり取りする方法として、現代のWebアプリケーションで広く使われています。しかし、適切に保護しないと、アプリケーション全体のセキュリティを損なう脆弱性につながる可能性があります。こうした脆弱性を防ぐベストプラクティスの1つが、JWTに有効期限を設定することです。

JWTに有効期限を設定することが重要な理由

JWTに有効期限を設定すると、JWTを使用できる期間を制限できます。有効期限を過ぎるとJWTは無効になり、ユーザーはアプリケーションにアクセスするために新しいJWTを取得する必要があります。これにより、ユーザーがログアウトした後であっても、攻撃者が古いJWTを使ってアプリケーションにアクセスすることを防げます。

JWTに有効期限を設定する方法

JWTのペイロードに有効期限のクレームを追加することで、有効期限を設定できます。有効期限のクレーム(exp)の値は、JWTが失効する時刻を表すUnixタイムスタンプです。JWTの検証時に、サーバーはexpクレームを確認して、JWTがまだ有効かどうかを確かめます。

PythonでJWTに30分の有効期限を設定する例を紹介します。

import jwt
import datetime

# Set the expiration time to 30 minutes from now
exp_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=30)

# Encode the JWT with the expiration claim
jwt.encode({'some_payload': 'some_value', 'exp': exp_time}, 'secret_key', algorithm='HS256')

セキュリティ問題をSnykで検出する実践例

Snykは、JWTの有効期限設定に関するセキュリティ問題の検出に役立つ開発者向けセキュリティツールです。たとえば、Snyk Open Sourceはアプリケーションの依存関係をスキャンし、JWTに関連する脆弱性を含む既知の脆弱性を検出できます。

Snyk Open Sourceは、アプリケーションで古いバージョンや安全でないバージョンのJWTライブラリが使われていないかも特定できます。JWTライブラリを最新の状態に保つことで、JWTに関連するセキュリティ脆弱性にパッチが適用されていることを確認できます。

おすすめのオープンソースパッケージ

PythonでJWTの有効期限を設定するのに役立つオープンソースパッケージがいくつかあります。その1つがPyJWTです。JWTのエンコードとデコードに加えて、有効期限も簡単に設定できます。

PyJWTをインストールするには、pipを使います。

pip install PyJWT

インストール後は、PyJWTを使ってJWTに有効期限を設定できます。

import jwt
import datetime

# Set the expiration time to 30 minutes from now
exp_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=30)

# Encode the JWT with the expiration claim using PyJWT
jwt.encode({'some_payload': 'some_value', 'exp': exp_time}, 'secret_key', algorithm='HS256')

JWTに有効期限を設定することは、アプリケーションのセキュリティ脆弱性の防止に役立つ重要なベストプラクティスです。SnykのようなツールやPyJWTのようなオープンソースパッケージを活用することで、アプリケーションの安全性を確保し、最新のセキュリティベストプラクティスに対応できます。

JWTのセキュリティベストプラクティスが極めて重要な理由

まとめると、JWTのセキュリティベストプラクティスに従うことは、Webアプリケーションの安全性と完全性を確保するうえで非常に重要です。これまで見てきたように、JWTを適切に扱わないと、深刻な脆弱性や侵害を招き、不正アクセス、データ漏えい、評判の低下につながる可能性があります。JWTを扱う際のセキュリティに関するベストプラクティスを3つ実践することで、こうしたリスクに直面する可能性を大幅に減らせます。

  1. JWTを安全に保存する:JWTをローカルストレージやCookieに保存するのは避け、HttpOnly Cookieやサーバー側のセッション管理など、より安全な方法を選びましょう。

  2. JWTを検証する:JWTを受け取ったら必ず検証し、署名を確認して改ざんされていないことを確かめましょう。無効なトークンを安全に扱えるよう、適切なエラー処理を実装してください。

  3. 強力な暗号化とアルゴリズムを使う:RS256などの堅牢な暗号化アルゴリズムを選び、不正なトークンの作成や変更を防ぐために秘密鍵を安全に管理しましょう。

Snykでアプリケーションのセキュリティを強化

Webアプリケーションのセキュリティをさらに強化するために、Snykに登録してみましょう。Snykは、ソースコード、オープンソースパッケージ、コンテナイメージ、クラウド構成をスキャンし、脆弱性を検出する強力な開発者向けセキュリティツールです。Snyk Open Sourceを使えば、Pythonプロジェクトとその依存関係にあるセキュリティ問題をすばやく特定して修正できます。

たとえば、Pythonプロジェクトで古いバージョンや脆弱性のあるJWTライブラリが使われていないかを検出し、安全なバージョンにアップグレードするための具体的な推奨事項を提示できます。

# Requirements.txt file in your Python project
pyjwt==1.7.1

たとえば、pyjwtのバージョン1.7.1に脆弱性があることをSnykが通知し、2.1.0など、より安全なバージョンへのアップグレードを提案する場合があります。

# Updated Requirements.txt file
pyjwt==2.1.0

Snykを開発ワークフローに組み込めば、セキュリティ問題が深刻化する前に先回りして発見、対処し、アプリケーションの安全性とコンプライアンスを維持できます。

今すぐ対策を始めましょう

Webアプリケーションのセキュリティを運任せにしないでください。JWTを扱う際のベストプラクティスに従い、Snykに登録して、脆弱性やリスクからアプリケーションを守る包括的なセキュリティソリューションを利用しましょう。Snykなら、業界標準に準拠した安全なアプリケーションを開発できます。Webアプリケーションを保護するために、今すぐ無料アカウントを作成しましょう。