web-dev-qa-db-ja.com

Angular RESTful原則を破ることなく、認証と承認のベストプラクティスですか?

私はかなりの数のSO認証と承認についてのスレッドをRESTとAngularで読みましたが、私はまだ素晴らしい解決策があるとは感じていませんある程度のバックグラウンドとして、私はサポートしたいAngularJSでアプリを構築することを計画しています:

  1. 制限付きゲストアクセス
  2. 認証されたアプリケーションへのロールベースのアクセス
  3. APIを介した認証

REST APIへのすべての呼び出しはSSL経由で発生する必要があります。RESTful原則を破ることなく、つまりサーバーにセッション状態を保存しないでアプリをビルドしたいと思います。もちろん、クライアント側で許可に対して行われることはすべてサーバー側で強化する必要があります。各リクエストで状態全体を渡す必要があるため、何らかのトークンを渡して、 RESTリクエストを受信するバックエンドサーバーは、呼び出しを認証および承認できます。

とはいえ、私の主な質問は認証に関するものです-ここでのベストプラクティスは何ですか?多くの異なるアプローチが議論されているようですが、私が見つけたほんのいくつかを紹介します。

同様の質問がありました( AngularJSベストプラクティスアプリケーション認証 )が、答えを誤解していない限り、サーバーセッションを使用する必要があることを意味しているようで、RESTfulの原則に違反しています。

Amazon AWSとGeorge Reeseの記事に関する私の主な懸念は、消費者がエンドユーザーではなくプログラムであることを前提としているようです。共有シークレットは事前にプログラマーに発行でき、プログラマーはそれを使用してここで呼び出しをエンコードできます。ここではそうではありません。ユーザーに代わってアプリからREST APIを呼び出す必要があります。

このアプローチで十分でしょうか?セッションリソースがあるとします。

POST/api/session

ユーザーの新しいセッションを作成する

セッションを作成するには、POST "username"と "password"を含むJSONオブジェクトが必要です。

{
    "email" : "[email protected]",
    "password" : "password"
}

カールの例

curl -v -X POST --data '{"username":"[email protected]","password":"password"}' "https://app.example.com/api/session" --header "Content-Type:application/json"

応答

HTTP/1.1 201 Created {
    "session": {
        "id":"520138ccfa4634be08000000",
        "expires":"2014-03-20T17:56:28+0000"
    }
}

ステータスコード

  • 201-作成され、新しいセッションが確立されました
  • 400-不正な要求、JSONオブジェクトが無効であるか、必要な情報が欠落しています
  • 401-不正、メール/パスワードの組み合わせを確認
  • 403-アクセス拒否、無効化されたアカウントまたはライセンスが無効

明確にするために、HATEOASの詳細は省略します。バックエンドでは、新しい期間が制限された新しいセッションキーが作成され、ユーザーに関連付けられます。後続のリクエストでは、これをHTTPヘッダーの一部として渡すことができます。

Authorization: MyScheme 520138ccfa4634be08000000 

次に、バックエンドサーバーは、リクエストからこれをダイジェストし、関連するユーザーを見つけて、リクエストの承認ルールを実施する責任があります。セッションの有効期限も更新する必要があります。

これらすべてがSSLを介して行われている場合、どのような種類の攻撃からも保護する必要がありますか?セッションキーを推測してヘッダーに配置しようとする可能性があるため、ユーザーGUID=をセッションキーに追加して、ブルートフォース攻撃をさらに防ぐことができます。

私が積極的にプログラミングを始めてから数年が経ちましたが、ちょうどここでスイングに戻りました。私がこれまで読んだことに基づいてコミュニティで私のアイデアを実行し、リトマス試験に合格するかどうかを確認したいだけで、私が鈍いまたは不必要に車輪を再発明している場合はおologiesびします。

41
austrum

誰かがREST認証について尋ねるとき、私はアマゾンウェブサービスに従い、基本的に「それを行う」ことを提案します。理由は、「群衆の知恵」の観点から、AWSは問題は、多くの人よりも安全なリクエストを作成することについて、最も多くのことを熟知し、気遣っている人々によって頻繁に使用され、徹底的に分析され、検査されます。立ち上がる」ことは、AWSよりも悪いことをすることができます。

現在、AWSはトークン技術を使用せず、共有シークレットとペイロードに基づいた安全なハッシュを使用しています。おそらく、より複雑な実装です(すべての正規化プロセスなど)。

しかし、それは機能します。

欠点は、アプリケーションが個人の共有シークレット(つまりパスワード)を保持する必要があり、またサーバーがパスワードのプレーンテキストバージョンにアクセスする必要があることです。これは通常、パスワードが暗号化されて保存され、必要に応じて復号化されることを意味します。また、サーバー側のキー管理やその他のことを、より安全なハッシュ手法よりも複雑にします。

もちろん、トークンパッシングテクニックの最大の問題は、中間者攻撃とリプレイ攻撃です。 SSLは、これらをほとんど自然に軽減します。

もちろん、OAuthファミリも考慮する必要があります。これらのファミリには、特に相互運用性に関する独自の問題がありますが、それが主要な目標でない場合は、テクニックは確かに有効です。

あなたのアプリケーションにとって、トークンリースは大したことではありません。アプリケーションは、リース期間内に動作するか、リースを更新できる必要があります。そのためには、ユーザーの資格情報を保持するか、ユーザーの資格情報を再入力する必要があります。トークンを他の何かと同様に、ファーストクラスのリソースとして扱うだけです。実用的な場合は、他の情報をリクエストに関連付けてトークンにまとめ(ブラウザーの署名、IPアドレス)、一部のローカリティを強制します。

同じリクエストが2回送信される可能性のある(潜在的な)リプレイの問題に引き続き対応しています。典型的なハッシュ実装では、タイムスタンプは署名の一部であり、リクエストの寿命を制限することができます。この場合、異なる方法で解決されます。たとえば、各リクエストはシリアルIDまたはGUIDで送信できます。リクエストが既に再生されたことを記録して、再び発生しないようにすることができます。

15
Will Hartung

これは、Angularで構築された認証およびログインサービスに関する素晴らしい記事です。

https://medium.com/opinionated-angularjs/7bbf0346acec

9
Sten Muchow

このSOの質問はRESTについての私の理解をまとめるのに良い仕事をします

セッションは本当にRESTfulnessに違反していますか?

トークンをセッションに保存している場合でも、サーバー側で状態を作成しています(セッションは通常1つのサーバーにのみ保存されるため、これは問題です。これはスティッキーセッションまたは他のソリューションで軽減できます)。

RESTfulサービスを作成する理由が何であるかを知りたいのですが、おそらくこれはそれほど大きな問題ではないからです。

すべてのリクエストとともにトークンを本文で送信する場合(すべてがSSLで暗号化されているためこれで問題ありません)、状態を事前に知らなくても、任意の数のサーバー(負荷分散)でリクエストを処理できます。

簡単に言えば、RESTfulな実装を目指すことは良い目標ですが、純粋にステートレスであることは、認証と承認の検証に関して、確かに余分な複雑さを生み出します。

これまでのところ、RESTを念頭に置いてバックエンドの構築を開始しました。意味のあるURIを作成し、正しいHTTP動詞を使用しますが、認証を簡単にするためにセッションでトークンを使用します(複数のサーバーを使用しない場合)。

私はあなたが投稿したリンクを読んで、AngularJSはクライアントだけに焦点を当てているようで、その記事でサーバーに明示的に対処していないようです。彼は別のサーバーにリンクしています(Nodeユーザーはここでの解釈が間違っていても許します)が、サーバーはクライアントに依存しているように見えます。

0
shaunhusain