web-dev-qa-db-ja.com

JWTによるアクセス許可ベースのアクセス制御

トークンベースの認証(JWT)でユーザーを認証するシングルページアプリケーション(SPA)フロントエンドに、アクセス許可ベースのアクセス制御を導入したいと思います。

許可要件:

私のSPAでは、必要な各(html)要素が権限にマップされ、ユーザー権限の可用性に応じて、要素が表示または非表示になります。複数の要素を同じ権限にマッピングできます。

権限の数:〜100

私が解決する必要がある問題は:

特定のフロントエンド要素の表示とアクセスを制御する権限をバックエンドからSPAに効率的に渡す方法。

これを実装する方法の異なるオプションを使用して2つの可能なアプローチについて考えています。

アプローチ1

権限ベースの認証に関するほとんどすべてのガイドと例では、権限はjwtトークンに含まれているようです:

  1. ユーザーはウェブアプリにログインします
  2. ユーザーが認証され、サーバーがjwtトークンをSPAに返します。

    オプションA

    Jwtトークンには許可ごとに1つのクレームが含まれます。

    オプションB

    Jwtトークンには値としてすべてのユーザー権限がカンマ区切りまたは構造化されている1つの要求が含まれます。

  3. SPAはjwtトークンを解析し、権限を取得します。

アプローチ2

上記のソリューションは、ネットワークトラフィックの観点からは効率的に聞こえないため、2番目のアプローチを次に示します。

  1. ユーザーはウェブアプリにログインします
  2. ユーザーが認証され、サーバーがjwtトークンをSPAに返します。
  3. Jwtが正常に取得されるとすぐに、クライアントは別のリクエストでユーザーの権限をリクエストします。
  4. アクセス許可が取得されると、ブラウザセッションにキャッシュされます。

質問:

  • JWTクレームはユーザー権限を渡すのに適していますか?
  • 100のクレームは、トークンで渡される大きなサイズではないでしょうか?
  • ユーザー権限が変更された場合にキャッシュを検証する必要があるという欠点を除いて、2番目のアプローチで問題が発生しますか?
2
panda

Imhoあなたはより安全なアプローチ1-オプションA( 理由を見る )を選択し、グループを作成してアクセス許可の数を減らし、フラグの可能性を活用する必要があります。

クライアントが持つことができる:

const accessMode = Object.freeze({
  none: 0,
  execute: 1,
  write: 2,
  read: 4
});

そして権限を組み合わせる:

file.accessMode = accessMode.read | accessMode.write;

サーバーは以下を発行します:

Claims.FileAccess: 6

またはTypeScriptについては、FileAccessの例をここで参照してください。 https://www.typescriptlang.org/docs/handbook/enums.html#computed-and-constant-members

2
andekande

この場合、JWTは存在しない問題に対する過度に複雑なソリューションのように思えます。あなたが述べたことから、これは実際のセキュリティ問題とは対照的に、プレゼンテーションの問題(たまたまaboutセキュリティ)です。クライアント側で実行されるすべてのコードは信頼できず、クライアントはいつでもそのビットにアクセスできると想定する必要があります(例:F12開発者ツールを使用してフィールドを編集可能にするのは簡単です)。

だからあなたの質問に答えるには:

  • いいえ、JWTは、単一のサーバーのみを処理している場合、クレームを渡すのに適した方法ではありません。
  • 100クレームは、それらを格納する方法に応じて、JWTを大きくする可能性があります(例:それぞれの名前付き文字列は大きくなり、ビットごとのフィールドは大きくなりません)
  • 2番目のアプローチは問題ありません(JWTかどうか)

JWTの使用

JWTは、切断されたシステム間でクレームを渡すのに役立ちます。たとえば、サーバーAがクライアントにJWTを発行し、クライアントがそのクレームをサーバーBに提示します。単純なトークン(ワンタイムパスワード)の場合、これにはサーバーが必要です。 BはサーバーAに接続して、このトークンが有効かどうかを確認します。 JWTを使用すると、サーバーBがサーバーAの署名鍵(通常は公開鍵)を持っている限り、二次通信チャネルを実行する必要なく、サーバーAによって署名されたJWTを検証できます。

サーバーと通信するSPA

より簡単な方法は、権限の配列を返すことです。最初にログインするときにこれを行うのがおそらく最も理にかなっていますが、直後に別の呼び出しを行うこともできます。セッション中に権限が変更される可能性が高く、更新を必要とせずにそれをアプリに反映させたい場合は、権限のセットを更新する別の方法が必要になります。

サーバーサイドから実行されているすべてのアクションを検証する必要があることに注意してください-クライアントサイドではセキュリティenforcementを実行できません。これはコントロールの範囲外であるためです。

2
gregmac