私はWeb開発にかなり慣れていないため、Webアプリケーションを構築する方法を学んでいます。マルチユーザーアプリケーション用の認証メカニズムを設定する方法を理解する際に問題に直面しています。アーキテクチャについて詳しく説明します。
ここには2つのWebサーバーがあります。フロントエンドアプリケーション(Angularで記述)とバックエンドREST APIです。2つは別々に存在し、より分離されたシステムを備えています(バックエンドがデータを提供します) 、フロントエンドがそれを表示します)、サードパーティが独自のクライアント側アプリケーションを実装できるようにします。それが適切かどうかはわかりませんが、バックエンドAPIは PostgREST ですPostgreSQLデータベースの上にあるWebサーバー。
前述のとおり、これはマルチユーザーアプリケーションなので、クライアントの認証も設定したいと思います。私のアーキテクチャのコンテキストでは、www.domain.com
からapi.domain.com
、およびclient
からwww.domain.com
の認証を設定することを意味します。ブラウザベースのクライアントから直接アクセスされることはないため、トークンベースの認証を使用してバックエンドAPIにアクセスする方が理にかなっていると思います。 www.domain.com
での認証については、トークンベースの認証またはセッションベースの認証のどちらかを選択するオプションがあると思います。正しく設定されている場合、認証プロセスは次のようになります。
問題は、client
-www.domain.com
認証からwww.domain.com
とapi.domain.com
の間の認証への変換を設定する方法が理解できないことです。このような状況でのブラウザとフロントエンドの通信には、どのような認証メカニズムが最適ですか?認証をバックエンドAPIに「転送」する方法これを達成する別の方法はありますか?
状況は非常に一般的です。 APIのクライアントは、アプリケーションを使用する実際の人々ではなく、最終ユーザーとAPIの間のアプリケーション(Webアプリケーション、Android/iOSアプリケーション、またはバッチスクリプト)です。ただし、これらのAPIクライアントはすべてユーザーのデータにアクセスできるため、問題が発生します。APIは、ユーザーのデータへの無制限の読み取り/書き込みアクセス権を、アクセスするクライアントに与えることは想定されていません。
何故なの? 2つの理由があります。
APIが公開されている場合、つまり誰でもクライアントを作成できる場合は、すべてのユーザーにユーザーのデータへのアクセスを許可します。これは、ほとんどすべての場合に受け入れられるわけではありません。
APIが公開されていない場合、つまり、あなたがクライアントを追加できるのはあなただけである場合、作成できるクライアントの制限がすぐにわかります。サーバーでホストされているため、Webアプリケーションは問題ありません。他のすべてはそうではありません。これは、たとえば、モバイルデバイス用のクライアントアプリやデスクトップPC用のアプリケーションを持つことは不可能であることを意味します。そのようなクライアントとサーバー間のやり取りは、簡単に解読、分析、改ざんできるためです(HTTPSは、ここでは、デバイスの所有者がカスタムルート証明書を生成できるためです。
これは、特定のアプリケーションがAPIを介して自分のデータにアクセスすることを承認することを確認するのはユーザーに属していることを意味します。 GoogleドライブまたはFacebookデータにアクセスする必要があるアプリケーションを使用する場合、この種の相互作用をよく見ることができます。GoogleとFacebookはそれぞれ、特定のアプリケーションのデータへのアクセスを許可するかどうかを確認し、正確にはアプリケーションがアクセスできるようになり、それはあなたが承認または拒否することに属します。
ただし、これには1つの制限があります。ユーザーが https://www.example.com/ にアクセスし、 https://api.example .com /http://www.example.com/ が自分のデータにアクセスできるかどうかを尋ねると、彼らは理解しません。つまり、信頼できるクライアントのリストが必要です。この場合、WebアプリケーションはAPIの信頼できるクライアントであり、すべてのユーザーのデータへの無制限のアクセスが許可されます。
ただし、これは必ずしもPOST http://www.example.com/login
。これは1つの方法ですが、OpenIDまたはOAuth 2.0を使用するのがより簡単な方法です。これはデファクトユーザーを認証する標準的な方法。認証を行うためにGoogleなどの他の誰かに依存している場合は、パスワードを扱う必要がないという大きなメリットがあります。
あなたが説明したアーキテクチャは今のところかなり一般的です、私はあなたが一つだけ欠けていると思います:
アプリとバックエンドが異なるドメインにある場合、Cookieを使用してトークンを保存することはできません。一般的なプロセスは次のとおりです。ユーザーがアプリ経由で資格情報をバックエンドに投稿し、バックエンドがトークンを作成し、アプリがトークンをlocalstorageに保存します。アプリからバックエンドへの後続のすべてのリクエストで、リクエストのAuthorizationヘッダーにトークンを追加します。
認証と承認はバックエンドで行われます。ログインリクエストへの応答で、バックエンドは「ユーザーは管理者であり、ユーザーはxyzの権限を持っている」などの情報をアプリに提供できます。その情報に基づいて、アプリはリンクと機能を非表示/表示します。
確かに、ユーザーはその応答を操作して、自分自身を管理者または何かにすることができます-その結果、ユーザーには管理者リンクが表示されます。しかし、彼がこれらのリンクを使用して、バックエンドのこれらの管理エンドポイントにリクエストを送信しようとすると、バックエンドの認証コンポーネントが起動してリクエストを拒否し、403で応答するはずです。