Open5

認証/認可

expsh13expsh13

認証/認可

  • 認証は、ネットワーク、アカウント、アプリケーション、システムやその他のリソースへのアクセスを許可する前に、ユーザーの身元を確認するプロセスです。
  • 認可は、データ、アプリケーション、ネットワークなどのシステムリソースに対するユーザーのアクセスレベルを決定するプロセスです。
expsh13expsh13

SSO(シングルサインオン)

通常、システムを利用する際はシステムごとのユーザー認証が必要になります。一方でシングルサインオンとは、1度のユーザー認証によって業務アプリケーションやクラウドサービスといった、複数のシステムの利用が可能になる仕組みを指します。SSO を使用しない場合、さまざまなウェブサイトの複数のパスワードを覚えておく必要があります。
シングルサインオンには、主に2つの認証方式があります。

  • リバースプロキシ方式
    Web上で認証を行う仕組みです。リバースプロキシと呼ばれる中継サーバーで認証を行い、リバースプロキシ経由で対象システムにアクセスします。既存システムに影響を与えることなく事前検証ができるため、手軽に導入ができます。
  • SAML(サムル)認証方式
    異なるインターネットドメイン間でユーザー認証を行うための標準規格です。SAML認証を用いたログインの際、ユーザー認証に加えて、ログインする人の属性情報も同時に認証できるため、ユーザーのアクセス範囲を制限できます。これにより、特定の部署に所属する人しか、アクセスさせない、使える機能を制限する、といったアクセス制御が可能になり、セキュリティ対策が強化できるメリットもあります。

Gmailにログインすると、他のGoogleサービス(Google スプレッドシート、Googleドキュメント、YouTubeなど)に自動的にログイン状態となり、それぞれのサービスで個別にログイン操作をする必要がなくなります。これがSSOの典型的な利用例です。

仕組み

  1. ユーザーがアプリケーションにアクセスすると、アプリはユーザーが未認証であることを検出し、認証リクエストをSSOサービス(IDプロバイダー)にリダイレクトします。この時点でアプリがトークンを生成するのではなく、認証要求を送ります。
  2. SSOサービスは、ユーザーが既に認証済み(同一セッション内で他のアプリに既にログイン済み)かどうかを確認します。認証済みの場合、ユーザーに再度認証を求めることなく、認証トークンを生成してアプリケーションにリダイレクトします。
  3. ユーザーがまだ認証されていない場合、SSOサービスはログイン画面を表示し、ユーザー名とパスワードの入力を求めます。
  4. 認証情報が正しく検証された場合、SSOサービスは認証トークン(通常はSAMLアサーションやJWTなど)を生成し、ユーザーをそのトークンと共に元のアプリケーションにリダイレクトします。
  5. アプリケーションはそのトークンを検証し、有効であればユーザーにアクセスを許可します。
    認証に失敗した場合、SSOサービスはエラーメッセージを表示し、再試行を促します。複数回失敗した場合、アカウントロックなどの対策が実施されることがあります。

SSO サービス
SSO サービスは、ユーザーがログインするときにアプリケーションが利用する中心的なサービスです。認証されていないユーザーがアプリケーションへのアクセスを要求すると、アプリはそのユーザーを SSO サービスにリダイレクトします。次に、サービスはユーザーを認証し、元のアプリケーションにリダイレクトします。サービスは通常、専用の SSO ポリシーサーバーで実行されます。
SSO トークン
SSO トークンは、ユーザー名や E メールアドレスなどのユーザー識別情報を含むデジタルファイルです。ユーザーがアプリケーションへのアクセスを要求すると、アプリケーションは SSO サービスと SSO トークンを交換してユーザーを認証します。

https://www.ntt.com/bizon/glossary/e-s/sso.html
https://aws.amazon.com/jp/what-is/sso/

expsh13expsh13

OpenID Connect(OIDC)

OpenID ConnectはOAuth 2.0 の拡張仕様であり、SSOを実現するための具体的な認証プロトコル・技術規格の一つでもある。OAuth 2.0 はアクセストークンを発行するための処理フローを定めていますが、それを流用し、ID トークンも発行できるようにしたのが OpenID Connect なのです。
https://miro.com/app/board/uXjVLo9wgvQ=/?moveToWidget=3458764615029436990&cot=14
https://qiita.com/nabeatsu/items/380058915629c0ce795e

IDトークン

OIDC (OpenID Connect) や OAuth 2.0 を実装する 認可サーバー (Azure AD / Entra IDなど) が発行。ユーザーが認証済みかどうかを確認。
https://qiita.com/TakahikoKawasaki/items/498ca08bbfcc341691fe

expsh13expsh13

OAuth 2.0

OAuth2.0は認可を行うためのプロトコルであり、ユーザー(リソースオーナー)が、クライアントアプリケーションにリソースへのアクセスを許可するためのプロトコルです。
例えば、googleのユーザープロフィールを利用したいアプリケーションは認可サーバー(Googleの認証システム)からアクセストークンをもらい、そのトークンを使用しリソースサーバーからプロフィールデータをもらうことができる
※認証のプロトコルではない。

役割

リソースオーナー(ユーザー)、クライアント(アプリ)、認可サーバー、リソースサーバーの4つの役割を定義

主な構成要素

アクセストークン: リソースへのアクセス権を表す短期間有効な鍵
リフレッシュトークン: アクセストークンの有効期限切れ時に新しいアクセストークンを取得するための長期的な鍵
スコープ: アクセス権限の範囲(例:読み取り専用、書き込み権限など)
認可グラント: アクセストークンを取得するための方法(認可コード、暗黙的、パスワード認証、クライアント認証)

https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be
https://qiita.com/TakahikoKawasaki/items/200951e5b5929f840a1f

expsh13expsh13

セッション管理

よく使用される認証方式にセッション認証、トークンベース認証がある。
セッションベース認証がサーバーに認証のための情報 (セッション ID とユーザー情報の対応) を持たせておくのに対し、トークンベース認証はサーバーにそうした情報を持たせずトークンの検証のみによって認証を行う点です。
セッションベース認証はステートフルであり、トークンベース認証はステートレスであるということです。これにより、セッションベース認証がステートフルな通信を実現できるというメリットを持つ一方で、トークンベース認証は (サーバーに認証のための情報を持つ必要がないため) ユーザーが増加した時のサーバー負荷がセッションベース認証よりも少なく、よりスケーラブルなシステムを実現できるというメリットを持ちます。

データベース

トークンベース認証と比較して、セキュリティが高いのは、セッションIDのみ(key)クライアントに渡すので、流出してもデータを直接改竄されることはない。セッション情報を持たせる場合は、こちらを選ぶとよさそう。流出者に攻撃できる点は同じ。

ログアウトした場合は、ブラウザでセッション ID を別の値に更新しつつ、サーバーでもセッション ID とユーザー情報の対応を破棄します。
これで元々のセッション ID を用いてユーザー情報やリソースにアクセスすることはできなくなるわけです。

通常 Web システムではバックエンドのサーバは冗長構成をとり、LB(ロードバランサ)でリクエストが負荷分散されます。また、スケールアウト/スケールインすることも考慮しなければいけません。
単一サーバ内でセッションデータを保持していた場合、1つ前にリクエストしたサーバ以外へルーティングされてしまうとセッションデータが取得できません。
そこで Redis などの Key/Value で取得できるデータベースを用意しておき、どのサーバからも取得できるようにしておく構成とすることが一般的です。

ステートレス(トークンベース)

ログアウトしたとき、サーバーは認証のための情報を持っていないため、単純にブラウザに保存していたアクセストークンを破棄します。トークンベース認証はトークンの検証のみによって認証を行うため、ブラウザで破棄されたとてアクセストークンそのものは依然有効なわけです。
そのため、もしもそのアクセストークンが悪意あるユーザーの手に渡っていた場合、正規のユーザーがログアウトした後でも、悪意あるユーザーはリソースにアクセスできてしまうのです。
対策として下記がある。

  1. アクセストークンの有効期限を短く設定することです。ただ単純にトークンの有効期限を短くするだけではユーザーに求める認証回数が増えユーザービリティが損なわれてしまうため、アクセストークンを新しいものに取り替える機能をもつトークン (= リフレッシュトークンと呼ばれており、アクセストークンよりも有効期限が長く設定されています) を活用して、セキュリティとユーザビリティのバランスを取ることが多いです。

Access Token
リソースに直接アクセスするために必要な情報を保持しています。つまり、クライアントがリソースを管理するサーバーにAccess Tokenを渡すとき、そのサーバーはそのトークンに含まれている情報を使用してクライアントが認可したものかを判断します。Access Tokenには通常、有効期限があり、存続期間は短いです。

Refresh Token
Refresh Token は新しいAccess Tokenを取得するために必要な情報を保持しています。つまり、特定リソースにアクセスする際に、Access Tokenが必要な場合には、クライアントはAuthorization Serverが発行する新しいAccess Tokenを取得するためにRefresh Tokenを使用します。一般的な使用方法は、Access Tokenの期限が切れた後に新しいものを取得したり、初めて新しいリソースにアクセスするときなどです。Refresh Tokenにも有効期限がありますが、存続期間はAccess Tokenよりも長くなっています。Refresh Tokenは通常、漏洩しないように厳しいストレージ要件が課せられます。Authorization Serverによってブラックリストに載ることもあります。

https://zenn.dev/ayumukob/articles/640cbf4a1ff3ed
2. サーバーにアクセストークンのブラックリストを持たせておく。流出の恐れがあるアクセストークンをブラックリストに登録しておき、トークンを検証するタイミングでブラックリストの確認も行うようにします。

https://zenn.dev/tanaka_takeru/articles/3fe82159a045f7

セッション

通信などにおける論理的な意味での開始から終了まで。
セッション管理は、Webサーバー上でサービスを提供するといった際に、アクセスしているユーザーの識別や処理の状態を管理するために必要になります。

JWT(JSON Web Token)認証

JWTは、トークンベースの認証です。トークンベースの認証では、アプリケーションはユーザーのログイン状態を保持しません。
ユーザーは、ログインしたい時や情報を得たいときなど、アプリケーションにHTTPリクエストを送ります。その時に、事前に発行されたJWT(=トークン)を、1つ1つのリクエストに毎回一緒に含めて送ります。 そしてアプリケーション側はリクエストを受け取る度にそのJWTが有効かを検証することで、登録されているユーザーからのリクエストなのかを確認することができる、という仕組みです。

仕組み

https://qiita.com/asagohan2301/items/cef8bcb969fef9064a5c#5-jwt認証の流れ

JWTの作り方

JWTは『ヘッダ』『ペイロード』『署名』の3つの部分からできています。このJWTをアプリケーション側が発行してユーザーに渡し、ユーザーはリクエストの都度このJWTを含めて送ることになります。

  1. ヘッダ+ペイロードの作成
    ヘッダ
    ヘッダは、そのJWTを説明する部分。alg は必須の項目で、後の手順で署名をつけるときに使うアルゴリズムを表記します。typ はトークンのタイプで、JWT とします。
{
  "alg": "HS256",
  "typ": "JWT"
}

ペイロード
以下の例で入れているのは、sub がユーザーを一意に特定するための識別子、 exp がJWTの有効期限です。その他任意の項目を入れることができます。パスワードなどの機密情報は入れてはいけないことに注意してください。
この後の手順でペイロードをエンコードしますが、デコードすればもとのJSONに戻すことができるため、万が一JWTが何者かに盗まれてしまった場合に中身を簡単に見られてしまうためです。

{
  "sub": "1234567890",
  "exp": 1704704777
}

  1. ヘッダとペイロードのJSONを、それぞれBASE64URLエンコードし、ドットでつなぐ。
  2. 2で作成したものをヘッダの alg で指定したアルゴリズムと秘密鍵で署名します。その署名をさらにBASE64URLエンコードします。
  3. 2、3で作成したものをドットで繋ぐ。