この記事では、認証と承認を安全に実行するためのシステムについて説明します。まず、認証と承認の違いを理解しましょう。 、アプリケーションにアクセスするときに、ユーザーが誰であるかを証明するプロセスです。 認証とは 、アクセス ポリシー (つまり、認証されると何ができるか) を定義して適用するプロセスです。 承認とは この記事では、次の内容について説明します。 認証と承認が重要な理由 認証の仕組み 認証の仕組み 認証システムの設計 結論 認証と承認が重要な理由は何ですか? 会議中に、あなたが会話をリードしているとします。適切な相手に何かの更新や状況を尋ねるには、相手を識別 (つまり、 ) する必要があります。相手と機密データを共有する場合でも、相手を正しく認証する必要があります。ここで認証が重要になります。 認証 さて、同じ会議でいくつかの決定を下す必要があるとします。そのため、それらの決定を下す権限を持つ人が決定を下すべきであり、全員にすべてを許可するわけにはいきません。明らかに、一部の人は決定を下すのに十分な配慮を受けておらず、最悪の事態を招こうとする人もいます。そこで、承認が必要になります。 、特定の人に特定のアクティビティの権限を与えます。 承認は 認証はどのように機能しますか? 人物を認証するには、各人物に固有のフレーズを割り当て、その人物がそのフレーズと名前を正しく伝えれば、人物を識別できたと判断できます。これは、通常のユーザー名とパスワードのアプローチです。正しい資格情報が与えられると、システムは ID を有効とみなし、アクセスを許可します。これは 1FA または (SFA) として知られています。 シングル ファクタ認証 SFA はかなり安全ではないと考えられています。なぜでしょうか? ユーザーはログイン情報を安全に保つのが苦手だからです。多要素認証 (MFA) は、ユーザーが複数の方法で自分の身元を証明することを要求する、より安全な代替手段です。次のような方法があります。 使い捨てPIN番号/OTP 安全なサードパーティによって実行される認証アプリ(例:Google / Microsoft Authenticator) 生体認証 一度認証されると、ユーザーはアプリケーション上で自由に操作を実行し続けることになります。そして、アプリケーションは、ユーザーが操作中ずっとユーザーを認識し、ユーザーを忘れないようにする必要があります。理想的には、ユーザーが別のページに移動するたび、または何らかの操作を行うたびにパスワードの入力を求めるのはやりすぎです。そのため、ユーザーが資格情報を入力して一度認証された後は、そのユーザーの認証を維持する方法が必要です。これを と呼びます。 セッション管理 ユーザーの認証を維持する 2 つの方法: : ユーザーがブラウザで Web サイトにログインすると、サーバーはそのユーザーのセッションを作成し、セッション ID を割り当てます。このセッション ID は参照用にサーバーによって保存され、ユーザーに送り返されてブラウザの Cookie に保存されます。これで、ユーザーがリクエストを行うたびに、ブラウザはリクエストとともにセッション ID を送信します。これはリクエストの認証に役立ちます。そして、ユーザーがサイトにいる間は認証が維持されます。 セッションベースの認証 : この場合、サーバーは暗号化されたトークンを作成します。このトークンはユーザーに送信され、ブラウザーによってのみ HttpOnly Cookies として保存されます。ユーザー情報、権限、トークンの有効期限などの必要な情報はすべてトークン内で暗号化されます。トークンはサーバーへの呼び出しに送信されます。サーバーは秘密鍵を使用してトークンを復号化し、ユーザーを検証します。このトークンは一定間隔で更新されます。 トークンベースの認証 これら 2 つのアプローチの主な違いは、トークンベースの認証は あり、トークンをサーバー側に保存する必要がないことです。ただし、セッションベースの認証の場合、トークンはサーバー側でも保存する必要があるため、 なります。そのため、システムが拡張されたり、ユーザー数が増えたりすると、複雑な問題が発生します。 ステートレスで ステートフルに トークンベースの認証では、主に JWT (JSON Web Token) を使用します。 認証はどのように機能しますか? ユーザーが認証された後も、アクセス許可のあるリソースにのみアクセスできるようにする必要があります。機密データへの不正アクセスは大惨事を招く可能性があります。最小権限の原則により、企業は通常、デフォルトで絶対に必要なものにアクセスできるようなアクセス ポリシーを設定します。そして、それに応じて追加のアクセスが与えられます。アクセスをセグメント化する一般的な方法は次のとおりです。 : ユーザーは、設定された権限を持つ特定のグループ/ロールに割り当てられます。例: 管理者、メンバー、所有者。 ロールベースのアクセス制御 (RBAC) : ポリシーとルールに基づいて、承認時にアクセス権限を動的に決定します。ポリシーは、ユーザーの役割、職務、組織の要件に基づいています。 ポリシーベースのアクセス制御 (PBAC) : ユーザーは、役職、認定、トレーニング、場所などの環境要因などの属性に応じてアクセスを許可されます。 属性ベースのアクセス制御 (ABAC) : 各ユーザーまたはエンティティには、オンまたはオフにできる個別の権限があります。これは、携帯電話に新しいアプリをインストールし、付与する権限 (位置情報サービス、連絡先など) を決定するのと同様です。 アクセス制御リスト (ACL) ACL は、ABAC や RBAC よりも細かいレベルで頻繁に使用されます。たとえば、個々のユーザーに特定のファイルへのアクセスを許可する場合などです。ABAC と RBAC は通常、会社全体のポリシーとして導入されます。 認証システムの設計 要件 まず、システムの を定義することから始めましょう。 機能要件 : ユーザーが必要な情報を提供して登録できるようにします。 登録 : 資格情報に基づいてユーザーを認証します。 ログイン : ユーザー セッションを効率的に管理してセキュリティを確保します。 セッション管理 : ユーザーがパスワードを回復するための安全なプロセスを提供します。 パスワードの回復 : さまざまなユーザー タイプの役割と権限を定義します。 アクセス制御 : 監査のために認証イベントの詳細なログを保持します。 監査証跡 : 低レイテンシと高速応答時間を保証します。 パフォーマンス この記事の範囲では考慮しない 次のとおりです。 非機能要件は : 堅牢な MFA システムを実装します。 多要素認証 (MFA) : 暗号化、安全なストレージ、安全な通信を通じてデータ セキュリティを優先します。 セキュリティ : 増加するユーザー数とトランザクションを処理できるようにシステムを設計します。 スケーラビリティ : システムのダウンタイムを最小限に抑え、高い可用性を確保します。 信頼性 : シームレスなエクスペリエンスを実現する直感的なユーザー インターフェイスを開発します。 ユーザビリティ 容量推定 トラフィック推定 まず から始めましょう。月間平均トラフィックを 100,000 と仮定します。月間 10 万ユーザー トラフィックを見積もります。これは 1 秒あたり 0.04 リクエストに相当します。各リクエストに対して 90% の時間で 500 ミリ秒以内に応答する必要があります。つまり、p90 レイテンシは 500 ミリ秒である必要があります。 トラフィックの見積もり assumed_traffic_per_month = 100000 #requests assumed_traffic_per_day = assumed_traffic_per_month / 30 ~= 3350 (assuming on higher end; 3333.33 to be precise) estimated_time_per_request = 500 #ms; P90 of 500ms traffic_per_second = (assumed_traffic_per_month) / (30*24*60*60) = 0.04 : 500 ミリ秒 (システムの負荷に関係なく、許容可能な最大遅延) 特定のリクエストに対して負荷の高い処理が行われていないと仮定すると、1 つのインスタンスが要求を処理するのに要する平均容量は、当社の計算に基づいて約 35 ミリ秒です。 サービス レベル目標 (SLO) 上記のメトリックを使用して、さらに 2 つの を生成してみましょう。 派生メトリック : インスタンスあたりの許容バックログ: SLO を損なうことなくインスタンスが受け入れることができるリクエスト (負荷) の最大数。 容量 : インスタンスあたりのバックログ: 現在のトラフィックに基づいてユニット/インスタンスに流入するリクエスト (負荷) の合計数。 需要 したがって、 SLO = 500ms approx_response_time_for_one_request = 35 #ms capacity = SLO/approx_response_time_for_one_request = 500 / 35 ~= 20 load_on_one_instance = 0.04 instances_available = 1 demand = traffic_per_second / instances_available = 0.04 需要と利用可能な容量に基づいて、必要なインスタンスの合計数を計算しましょう。 total_units_required = demand / capacity = 0.04 / 20 = 0.002 ~= 1 したがって、1 つのインスタンスで、1 秒あたり 0.04 リクエストで、毎月 10 万リクエストを簡単に処理できます。各ユニットは、SLO を損なうことなく、1 秒あたり 20 リクエストを処理できます。 ストレージの見積もり 理想的には、認証と承認アクセスのために各ユーザーのユーザー詳細を保存する必要があります。5kb /ユーザーと仮定します。 monthly_new_users = 500 monthly_additional_storage = 500 * 5kb = 2500kb ~= 2GB したがって、毎月 500 人の新規ユーザーをオンボードすると仮定すると、2 GB の追加ストレージが必要になります。認証ログを保持する必要がある場合、各認証リクエストの保存には 2 KB かかると予想されます。 auth_request_size = 2kb #assumption monthly_storage = monthly_visitors * auth_request_size = 100,000 * 2KB ~= 200MB したがって、月間トラフィックが 10 万であると仮定すると、毎月 200 MB の追加容量が必要になります。 データベース設計 容量の見積もりが完了したので、機能要件をサポートするために必要なデータベースのスキーマを作成しましょう。 テーブルを簡単に見ていきましょう。6 つのテーブルを使用します。 ユーザー - すべてのユーザー情報を保存する 資格情報 - ユーザーが承認されたら、アクセス/更新の資格情報を保存します。 パスワード - ユーザーの暗号化されたユーザー パスワードを保存します。 PasswordRequests - 特定のユーザーに対するパスワード変更要求を保存します。 セッション - ユーザーがアクティブ セッションを行った日時と、最後のアクティビティがいつであったかを保存します。 ActivityApproval - 管理者によって検証される、特定のユーザーによって実行されたアクティビティの承認リクエストを保存します。 認証システムの高レベル設計 システムエンドポイント 終点 説明 /ログイン ユーザーの資格情報を認証します。 /ログアウト ユーザー セッションを終了し、認証トークンを取り消します。 /登録する 新しいユーザーを作成します。 /更新/:ユーザーID ユーザー情報を更新します。 /削除/:ユーザーID ユーザーアカウントを削除します。 /許可/:ユーザーID/:権限 ユーザーに特定の権限を付与します。 /取り消し/:ユーザーID/:権限 ユーザーの権限を取り消します。 /チェック/:ユーザーID/:リソース 特定のリソースへのユーザーのアクセスを確認します。 /create/:ユーザーID 新しいユーザー セッションを作成します。 /有効期限/:セッションID ユーザーセッションを期限切れにします。 /検証/:セッションID アクティブなユーザー セッションを検証します。 要件の充足 さて、すべての準備が整ったので、すべての要件をどのように満たすことができるかを見てみましょう。 登録 - 新しいユーザーがアプリケーションにアクセスする場合、次回アクセスしたときにユーザーを認証/識別できるように、ユーザーの詳細を保存する必要があります。 要件 - 新しいユーザーがアプリケーションにアクセスし、ユーザーの詳細とメール アドレスおよびパスワードを入力すると、データベースにキャプチャされます。ユーザーの詳細は、ユーザー テーブルに保存されます。パスワードは、暗号化された形式で資格情報テーブルに保存されます。 達成済み ログイン - 既存のユーザーがアプリケーションにアクセスする場合、ユーザーのアクションを承認/識別し、ユーザーに属するデータを表示できるように、ユーザーを識別する必要があります。 要件 - 既存のユーザーがアプリケーションにアクセスし、詳細、電子メール、パスワードを入力すると、パスワードがハッシュ化され、そのハッシュが資格情報テーブル内のユーザー用に保存されているハッシュと照合されます。一致した場合、ユーザーを正常に識別できたことになります。一致しない場合は、登録時に入力した正しいパスワードを入力する必要があります。このプロセスは と呼ばれます。 達成済み 認証 セッション管理 - ユーザーがユーザー名とパスワードを入力して認証した場合。ユーザーが今後のアクションを実行したり、機密データを表示しようとしたりするときに、パスワードを何度も再入力することなく、ログイン状態を維持できるようにする必要があります。 要件 - ユーザーが正常に認証された場合。認証サーバーは、クライアントと 2 つのトークン と を共有します。access_token には暗号化されたデータを含めることができ、セキュリティ上の理由から有効期限が短くなっています。クライアントが access_token を取得すると、リクエストの認証に役立つすべてのリクエストとともに access_token が返送されます。access_token の有効期限が切れると、クライアントは提供された refresh_token を使用して新しい access_token を要求する必要があります。これは、セッションの維持に役立ちます。 完了 (access_token refresh_token) パスワードの復元 - ユーザーがパスワードを忘れた場合、安全にパスワードをリセットできる必要があります。 要件 - ユーザーがパスワードを忘れた場合、パスワードを忘れた場合のページでメールアドレスを送信できます。ワンタイムコードが生成され、リンクがユーザーのメールに送信されます。ユーザーがコードとメールアドレスを含むこのリンクをクリックすると、パスワード回復リクエストが本物であることを安全に識別できます。そして、ユーザーに新しいパスワードの設定を提供します。こうして、パスワードを回復できるようになります。 達成済み アクセス制御 - ユーザーが特定のアクションを実行する場合、そのユーザーがそのアクションを実行するために認証されていることを確認し、認証された場合にのみアクションの実行を許可する必要があります。 要件 - 簡単にするために、アクションのリスト (1 ~ 12 とします) を維持します。各ユーザーについて、そのユーザーの認証済みアクションを維持します。ここで、ユーザーがアクション #id 4 を実行しようとしたとします。ユーザーにアクション 4 を実行する権限があるかどうかを確認します。権限がある場合は、先に進み、リクエストを完了します。権限がない場合は、権限不足のためリクエストが成功しなかったことを示します。 実行済み 監査証跡 - セキュリティ インシデントが発生した場合、十分なログを調べて、何が起こったのか、またはその原因は何であったのかについてのもっともらしい理由や手がかりを得ることができる必要があります。 要件 - このようなシナリオでは、サーバー上で発生するすべての認証アクションのログを保存できます。(a) ログイン要求ごとに、認証がいつ行われたか、どこから行われたか、IP アドレス、その他の関連詳細に関するログを保存します。(b) パスワード回復要求ごとに、開始された日時、どこから行われたか、IP アドレス、要求が完了したかどうか、その他の関連詳細に関するログを保存します。(c) さらに、ユーザーがアクションに対して承認/承認されなかったタイミングと、その承認者についてログを保存します。これらのログはすべて、何らかのシナリオを理解しようとする場合に、何が起こったかを示すことができるはずです。 達成済み パフォーマンス - 容量見積もりセクションで説明したパフォーマンス要件は、0.04 リクエスト/秒および 10 万リクエスト/月です。 要件 - 容量見積セクションで十分なサーバーを使用して要件をすでに処理しました。 達成済み 結論 この記事では、まず認証と承認の違いについて理解しました。次に、認証および承認システムを作成しました。これは、安全で、セキュリティが確保され、業界標準に準拠し、必要な要件をすべて満たしながらパフォーマンスを発揮します。今後、この記事の特定の部分を更新して、関連性を維持し、このようなシステムの構築に関するより多くの情報と洞察を網羅する可能性があります。