web-dev-qa-db-ja.com

REST APIセキュリティストアドトークンvs JWT vs OAuth

REST APIを保護するための最良のセキュリティソリューションを探しています。モバイルアプリケーションとAPIの量は日々増加しているためです。

さまざまな認証方法を試しましたが、まだ誤解がいくつかあるため、経験豊富な誰かのアドバイスが必要です。

私がこれらすべてをどのように理解しているかを教えてください。理解が間違っている場合はお知らせください。

REST APIは、一般にWEBと同様にステートレスである限り、各リクエスト(cookies、token ....)でいくつかの認証データを送信する必要があります。)ユーザーを認証する

  1. HTTPSを使用するトークン。私はこのアプローチを何度も使用していますが、HTTPSで十分です。ユーザーが正しいパスワードとログインを提供すると、応答としてトークンを受け取り、それを以降の要求に使用します。トークンはサーバーによって生成され、たとえば、ユーザー情報が格納されているテーブルとは別のまたは同じテーブルに格納されます。そのため、各リクエストに対して、サーバーはユーザーがトークンを持っているかどうかをチェックし、それはデータベースと同じです。すべてが非常に簡単です。

  2. JWTトークン。このトークンは自己記述的で、トークン自体に関するすべての必要な情報が含まれています。このトークンはサーバーによって秘密のキーワードで生成(署名)されるため、ユーザーは有効期限やその他の要求などを変更できません。これも明らかです。しかし、個人的には、トークンを無効にする方法という大きな問題があります。

  3. OAuth 2.サーバーとクライアント間で直接通信が確立されているときに、このアプローチを使用する必要がある理由がわかりません。私が理解している限り、OAuthサーバーは、他のアプリケーションがパスワードやログインを保存せずにユーザー情報にアクセスできるように、スコープが制限されたトークンを発行するために使用されます。これは、ユーザーが望むときにソーシャルネットワークに最適なソリューションです。一部のページにサインアップするために、サーバーは、たとえばTwitterやFacebookからユーザー情報を取得する権限を要求し、登録フィールドにユーザーデータなどを入力できます。

オンラインストアのモバイルクライアントを検討してください。

最初の質問は、最初のタイプのトークンよりもJWTを優先すべきですか?モバイルクライアントでログイン/ログアウトユーザーが必要な限り、トークンをどこかに保存する必要があります。JWTの場合、ログアウト時にトークンを無効にする必要があります。トークンを無効化するには、さまざまなアプローチが使用されます。その1つは、無効なトークンリスト(ブラックリスト)を作成することです。うーん。テーブル/ファイルのサイズは、トークンがテーブルに格納されてユーザーに関連付けられ、ログアウト時に削除される場合よりもはるかに大きくなります。

では、JWTトークンの利点は何ですか?

OAuthに関する2つ目の質問です。サーバーと直接通信する場合に使用する必要がありますか?トークンを発行するためだけにクライアントとサーバーの間のもう1つのレイヤーの目的は何ですか? oauthサーバーですが、メインサーバーです。理解できるように、OAuthサーバーは、サードパーティのアプリにユーザーの個人情報にアクセスするためのアクセス許可(トークン)を与えることのみを担当します。しかし、私のモバイルクライアントアプリケーションはサードパーティではありません。

111
CROSP

最初のケースを考えてみましょう。各クライアントは、セッションの期間中続くランダムなIDを取得します。次に、そのセッションに関連する情報をサーバー側のどこかに保存します。ファイルまたはデータベースにある可能性があります。 Cookieを介してIDを渡すとしますが、URLまたはHTTPヘッダーを使用できます。

セッションID/Cookie

長所:

  • クライアントとサーバーの両方を簡単にコーディングできます。
  • 誰かがログアウトしたときにセッションを破棄するのは簡単です。

短所:

  • サーバー側は、クライアントがログアウトしなかった期限切れのセッションを定期的に削除する必要があります。
  • すべてのHTTPリクエストには、データストアへのルックアップが必要です。
  • アクティブなセッションを持つユーザーが増えるにつれて、ストレージ要件が増大します。
  • 複数のフロントエンドHTTPサーバーがある場合、保存されているセッションデータは、それらすべてからアクセスできる必要があります。これは、1台のサーバーに保存するよりも少し手間がかかります。より大きな問題は、データストアが単一障害点になり、ボトルネックになる可能性があることです。

JSON Web Tokens(JWT)

2番目のケースでは、データはJWTに格納され、サーバーではなく渡されます。

長所:

  • サーバー側のストレージの問題はなくなりました。
  • クライアント側のコードは簡単です。

短所:

  • JWTサイズは、セッションIDよりも大きくなる可能性があります。各HTTPリクエストに含まれているため、ネットワークパフォーマンスに影響を与える可能性があります。
  • JWTに格納されたデータは、クライアントが読み取ることができます。これは問題である可能性があります。
  • サーバー側には、JWTを生成、検証、および読み取るためのコードが必要です。難しくはありませんが、学習曲線が少しあり、セキュリティはそれに依存しています。

    署名鍵のコピーを入手した人なら誰でもJWTを作成できます。これがいつ起こるかわからないかもしれません。

    一部のライブラリには、「none」アルゴリズムで署名されたJWTを受け入れるバグがあったため、誰でもサーバーが信頼するJWTを作成できました。

  • 有効期限が切れる前にJWTを取り消すには、失効リストを使用する必要があります。これにより、回避しようとしていたサーバー側のストレージの問題に戻ることができます。

OAuth

多くの場合OAuthは認証(つまりID)に使用されますが、ユーザーが購入してダウンロードする資格のあるコンテンツのリストなどの他のデータを共有するために使用できます。許可するために使用することもできます。サードパーティによって保存されたデータへの書き込みアクセス。OAuthを使用してユーザーを認証し、セッションデータにサーバー側ストレージまたはJWTを使用することができます。

長所:

  • ユーザーがサインアップまたはパスワードをリセットするためのコードはありません。
  • 検証リンクを含む電子メールを送信し、アドレスを検証するコードはありません。
  • ユーザーは別のユーザー名とパスワードを覚える/書き留める必要はありません。

短所:

  • ユーザーがサービスを使用するためには、サードパーティに依存しています。彼らのサービスがダウンしたり彼らがそれを中止したりする場合、あなたは何か他のものを理解する必要があります。例:ユーザーのIDが「[email protected]」から「[email protected]」に変更された場合、ユーザーのアカウントデータをどのように移行しますか?
  • 通常、プロバイダーごとにコードを記述する必要があります。例:Google、Facebook、Twitter。
  • あなたまたはあなたのユーザーはプライバシーの懸念があるかもしれません。プロバイダーは、どのユーザーがサービスを使用するかを知っています。
  • プロバイダーを信頼しています。プロバイダーは、あるユーザーに対して有効なトークンを他のユーザーに発行することができます。これは合法的な目的のためであるかどうかにかかわらずです。

雑多

  • 複数のユーザーがセッションIDとJWTの両方をコピーして使用できます。クライアントのIPアドレスをJWTに保存して検証できますが、クライアントがWi-Fiからセルラーにローミングすることはできません。
88
Chad Clark

元のトークンを無効にする必要がある理由を自問してください。

ユーザーがログインすると、トークンが生成され、アプリがオフになります。

ユーザーがログアウトを押すと、新しいトークンが生成され、元のトークンが置き換えられます。もう一度、すべてが順調です。

両方のトークンがぶら下がっているケースを心配しているようです。ユーザーがログアウトし、ログインしたトークンを使用してなんらかの理由でリクエストを行った場合はどうなりますか。このシナリオはどの程度現実的ですか?ログアウト時の問題だけですか、それとも複数のトークンが問題になる可能性のあるシナリオがたくさんありますか?

私自身、心配する価値はないと思います。誰かがあなたの暗号化されたhttpsデータを傍受してデコードしているなら、あなたははるかに大きな問題を抱えています。

元のトークンに有効期限を設定することで、さらに保護を強化できます。ですから、もし盗まれたりしてしまうのであれば、それは短期間だけ良いことです。

そうでなければ、サーバーに状態情報が必要になると思います。トークンをブラックリストに登録するのではなく、現在のトークンの署名をホワイトリストに登録します。

5
Cerad

ソルト値をユーザーと一緒に格納し、ユーザーのトークンの一部としてソルトを使用することにより、前述のJWT問題を処理できます。次に、トークンを無効にする必要がある場合は、ソルトを変更するだけです。

私はそれが2年になったことを知っていますが、今は実際にこれを別の方法で行うでしょう。私は、アクセストークンのライフタイムが比較的短く、たとえば1時間であることを確認します。また、サーバー上でステートフルな更新トークンを必ず使用し、誰かのセッションを終了したい場合は、サーバーから削除して更新トークンを取り消します。その後、1時間後、ユーザーはログアウトされ、アクセスを回復するには再度ログインする必要があります。

3
RibaldEddie
  1. 宣誓は認証プロトコルではなく、承認の標準またはプロトコルです。したがって、たとえばGoogleカレンダーに追加機能を使用する場合、それは誓いです。アプリは、要素のGoogleのAPI、または情報を渡すために探しているさまざまなフックへのURLリンクをリストします。承認が必要な場合は、OIDCまたはopenID接続が必要です。

  2. あなたのユースケースでは、私は上記のすべてのリルをお勧めします。 OIDCを使用する場合、ユーザー資格情報はHTTPS経由で認証サーバーに認証されます。リクエスト内には、ユーザーのユーザー名とパスワードに加えて、ランダムに生成されたアプリの一意の(クライアント)IDが含まれます。資格情報が有効でクライアントIDが有効な場合、サーバーはワンタイムパスワードで応答します。次に、ユーザーアプリはそのパスワードを取得してWebサービスに渡します。 Webサービスはパスワードを認証サーバーに返し、パスワードが正当であることを検証します。そうである場合、認証サーバーは承認/アクセストークン(AK)でWebサービスに応答します。これで、次の2つのアプローチのいずれかを実行できます。

    2.1そのトークンをクライアントアプリにアクセストークンとして保存できます。次に、Webサービスに更新トークンで応答させます。認証トークンの有効期間は数時間または数日で、更新トークンの有効期間は短くなります。更新トークンにはJWTを使用する必要がありますが、ランダムに生成された小さな文字列を更新トークンとして使用できます。この方法では、必ずしもすべてのリクエストでAKを渡す必要はありません。たとえば、5分経過してもサーバーがユーザーから更新トークンを取得できない場合は、ユーザーを切断し、すべてのトークンを無効にします(AKおよび更新)。ここでの唯一の欠点は、AKが侵害された場合、ユーザーシーズンが乗っ取られる危険を冒すことです。

    2.2(最も推奨)アクセストークンと認証は通常同じですが、技術的には2つの異なるトークンにすることができます。これは、ユーザーがすでに認証されていて、電話のOSハードウェアAPIを通じてユーザーの指紋または顔IDを使用している場合に最適です。電話で「はい」と表示された場合は、クライアントIDを送信して、認証情報のないAPIゲートウェイを介してキーストア/レポにアクセスします。ゲートウェイは、以前に生成した認証トークンで応答します。次に、アプリはそのトークンをWebサービスに送信でき、Webサービスはアクセストークンと更新トークンで応答します。その後、認証トークンを破棄し、アクセスと更新トークンを保持できます。

    ここでの考え方は、ユーザーが初めて認証されて認証トークンが生成された後、3か月の寿命を持つ可能性があるということです。クライアントの電話でそれを保持したくない場合は、それが危険にさらされるとユーザーが台無しになるからです。したがって、なぜそれを電話ではなくキーストアに保存するのか。これで、Webサービスが応答するアクセストークンの有効期間は1時間になり、更新トークンの有効期間は5分になります。更新トークンが機能している限り、セッションは存続します。その更新トークンの受信を停止すると、更新トークンとアクセストークンが無効になり、セッションが強制終了されますが、それでも認証トークンを保持できます。承認は、ES-256アルゴリズムを使用するJWTである必要があります。アクセストークンはRS-256を使用する必要があります。また、リフレッシュトークンはHS-256を使用できます。 RSおよびESで非対称暗号化を使用しないでください。非対称暗号化を生成するには、公開鍵と秘密鍵が必要です。 HSは対称暗号化を使用しますが、これは、それを生成するために1つのパスワードまたはキーのみが使用されることを意味します。

0
Gilles