web-dev-qa-db-ja.com

複数のサイトにわたる透過的なユーザーセッション(シングルサインオン+シングルサインオフ)

example.comexample.orgmail.example.compassport.example.orgの異なるドメインにいくつかのサイトがあります。すべてのサイトは共通のルックアンドフィールを持っており、同じユーザーベースを共有する必要があります。

そして、そのような極端な場合でも、すべてのサイトが透過的に(可能な限り)次の主要なプロパティを持つユーザーセッションを共有することを望んでいます。

  1. シングルサインオン。ユーザーがpassport.example.orgでサインオンし、他のサイトにアクセスすると、ログインしているものとして扱われる必要があります。

    ログインしたユーザーは、サイトヘッダーとさまざまなナビゲーションメニューで「こんにちは、$username」の挨拶を受け取り、アクセスできるサービスを一覧表示します。サインインしていない場合は、挨拶する代わりに、passport.example.org/signonを指す「サインオン」リンクがあります。

    信頼できるドメインのリストは既知であるため、これはOpenIDまたは自家製の軽量プロトコルを使用して実装するのはかなり簡単です。ユーザーが最初にサイトにアクセスしたとき、私はユーザーをpassport.example.orgの特別な認証エンドポイントにリダイレクトします。その後、ID情報(または「サインオンしていない」匿名ID)を含めて、ユーザーをサイレントにリダイレクトします。ほとんどのブラウザでは、これは完全に透過的です。明らかに、私はリダイレクトループと戦うためにナンス値を使用しています。

  2. シングルサインオン。ユーザーが次に任意のサイトにアクセスしたときに、任意のサイトのヘッダーで「サインオフ」をクリックすると、「サインオンしていない」と表示されます。

    OpenIDはこのために設計されていません。私の現在のアイデア(私はすでに部分的に機能する実装を持っています)は、ユーザーIDではなく、「グローバル」セッショントークンを送信し、DBでグローバルセッションテーブル(global_session_token↔ユーザーリレーション)を共有することです。

  3. ロボットとcookieless-ユーザーがサポート。サイトにはパブリックエリアがあり、Cookieのサポートなしでユーザーエージェントがアクセスできる必要があります。

    このため、(1)で説明したリダイレクトが問題になります。これは、ページリクエストごとに、ユーザーエージェントを認証エンドポイントにスローして戻すためです。これはロボットを混乱させるだけでなく、私のセッションデータベースを出生時のセッションで非常に迅速に汚染します。そして、私は絶対に「ねえ、あなたはクッキーを有効にしていない、離れて!」と表示したくありません。ページ、それは非常に失礼で失望するでしょう。ログインにはCookieのサポートが必要ですが、ユーザーがサイトの目的などを制限なく自由に読んでほしいと思っています。

    そして、私は明示的にセッションIDをURLに入れたくない私が言及したいくつかの透過的なクロスドメインリダイレクトを除いて。これを行うことはセキュリティの問題であり、一般的には悪いことだと思います。

    そして、ここで私はほとんどアイデアがありません。

わかりました。これは難しいことですが、Googleは実際に(google.comgoogle.lot‑of‑gTLDsgmail.comでこれを行っています。など)、そうですか?したがって、これは可能であるはずです。

プロトコル記述のアイデア(それが最善でしょう)またはシステムへのリンク(読むためのコードまたは見たり学んだりするためのライブサイト)のいずれかがすでにこのようなものを正常に実装していることに感謝します。

要約すると:共通ルート、共有ユーザーベース、シングルサインオン、シングルサインオフのない複数のドメイン、匿名での閲覧にCookieは必要ありません。

すべてのサイトは同じネットワーク上にあり(ただし、異なるサーバー上にあります)、部分的に同じPostgreSQLデータベースを共有しています(同じデータベースの異なるスキーム内にあります)。ほとんどのサイトはPython/Djangoで書かれていますが、一部のサイトではRailsでPHPおよびRubyを使用しています。フレームワークについて考えている間、言語に依存しないので、実装を指摘してくれてありがたいです。使用できなくても、そこでどのように行われるのかがわかれば、似たような実装を思いつくことができるかもしれません。

35
drdaeman

それでは、もう少し詳しく説明させてください。 (すべてのURLは架空のものです!)私が言ったように、訪問者は http://www.yourwebpage.com にアクセスし、ログインしたいことを示します。彼は http:/ /your.loginpage.org?return=http://www.yourwebpage.com/Authenticated ここで、ユーザー名とパスワードを入力する必要があります。
アカウント情報が有効になると、ログインURLで提供されたページに戻りますが、IDとして使用される追加のパラメーターがあります。したがって、彼は http://www.yourwebpage.com/Authenticated?ID=SharedSecret に移動します。ここで、SharedSecretは30秒以下有効な一時IDになります。
認証ページが呼び出されると、ページはyourwebpage.comとloginpage.orgの間で共有されるメソッドを呼び出して、SharedSecretのアカウント情報を検索し、より永続的なIDを取得します。この永続的なIDは、yourwebpage.comのWebセッションに保存され、ユーザーに表示されないようにする必要があります。
共有メソッドは何でもかまいません。両方のサーバーが同じマシン上にある場合、両方が同じデータベースにアクセスする可能性があります。そうしないと、Webサービスを介して別のサーバーと通信する可能性があります。これはサーバー間の通信であるため、ユーザーがロボットであるか、Cookieをサポートしていないかは関係ありません。この部分はユーザーには気づかれません。
対処する必要があるのは、ユーザーのセッションだけです。通常、ユーザーにはCookieに保存されているセッションIDが送信されますが、GETリクエストの一部としてURLの一部にすることもできます。ただし、フォームに非表示の入力フィールドを追加することで、セッションIDをPOSTリクエスト内に含める方が安全です。

幸いなことに、いくつかのWeb開発言語はすでにセッションサポートを提供しているため、セッションの維持やセッションIDの送信について心配する必要はありません。ただし、この手法は興味深いものです。また、セッションIDが乗っ取られるリスクがあるため、セッションは常に一時的なものである必要があることに注意する必要があります。

異なるドメイン上の複数のサイトを処理する必要がある場合は、最初にサーバー間の通信に取り組む必要があります。最も簡単なのは、同じデータベースを共有させることですが、保護を強化するために、このデータベースを中心にWebサービスを構築することをお勧めします。このWebサービスが、さらに保護を強化するために、独自のドメインからの要求のみを受け入れるようにしてください。
サーバー間接続がある場合、ユーザーはドメインを切り替えることができ、セッションIDを新しいドメインに渡す限り、ユーザーはログインします。ユーザーがCookieを使用している場合、セッションが失われる可能性はほとんどなく、再度ログインする必要があります。 Cookieがないと、閲覧ページ間でセッションIDが失われた場合、ユーザーが新しいCookieを取得するために再度ログインする必要がある可能性があります。 (たとえば、訪問者がGoogleにアクセスしてからサイトに戻ります。Cookieを使用すると、セッションをCookieから読み取ることができます。Cookieを使用しないと、GoogleがセッションIDを転送しないため、セッションが失われます。

異なるドメイン間でセッションIDを渡すことはセキュリティリスクであることに注意してください。セッションIDが乗っ取られる可能性があるため、他の誰かがあなたの訪問者になりすますことが可能になります。したがって、セッションIDは短命で、難読化する必要があります。ただし、ハッカーがセッションIDにアクセスしたとしても、アカウント自体に完全にアクセスすることはできません。彼はサーバー間の通信を傍受することができないため、ログインページに直接アクセスしない限り、ユーザー情報を使用してデータベースにアクセスすることはできません。

31
Wim ten Brink

AFAIK、Googleは「Google.com」ドメインにCookieを使用するだけです。しかし、Googleは一般的なログインメカニズムを可能にするOpenIDも使用しています。基本的に、これは特別なログインページにリダイレクトすることで機能します。このログインページは、ログインしているかどうかを検出し、ログインしていない場合はログインを求められます。それ以外の場合は、次のページに直接リダイレクトされます。

したがって、あなたの場合、ユーザーはsomepage.example.comを開き、このアプリのセッションにはログインIDがありません。したがって、ユーザーをlogon.example.bizにリダイレクトし、そこでユーザーがログインします。このページの後ろにもセッションがあり、そのセッションはユーザーがすでにログインしていることを通知します(またはそうでない場合、ユーザーは最初にログインします。)次に、ユーザーsomepage.example.com?sessionid=somethingをリダイレクトします。このセッションIDはsomepage.example.comのセッションに格納されます。次に、このセッションは、ユーザーがログオンしたことも認識し、ユーザーにとってはほとんど透過的であるように見えます。

実際には、ユーザーは2回リダイレクトされます。

5
Wim ten Brink

すべてのアプリケーションが1つのドメインにある場合は、ドメインレベルのCookieを使用してセッション制御を処理できるため、それほど難しくはありません。 (Cookieを使用しないセッション管理は困難ですが、実行できますが、困難です。)

ただし、example.comドメインのサイトと、example.orgドメインのサイトを指定しました。

私のgooglesigh-inやorkut.comの他のサイトで少し遊んでみると、認証情報が必要なページにアクセスすると、アカウントログイン用の共通サイトにリダイレクトされ、元のサイトにリダイレクトされるようです。サイト、おそらくURLで何らかのセッショントークンを渡します。このことから、orkut.comサーバーはgoogle.comサーバーと直接通信して、トークンを確認し、必要なその他のユーザー情報を取得します。

必要に応じてドメインレベルのCookieに関する詳細情報

foo.example.combar.example.com,のように2つのサイトがある場合は、ホストに固有のCookieを設定できますが、ドメイン上のすべてのホストに表示されるドメインのCookieを設定することもできます。

したがって、foo.example.comfoo.example.comにCookieを設定でき、それ自体のみが表示されますが、ドメインexample.com,にCookieを設定することもでき、ユーザーがbar.example.comにアクセスすると、この2番目のCookieも表示されます。

ただし、サイトsnafu.example.org,もある場合、example.orgexample.comは2つの完全に異なるドメインであるため、fooが設定したこのドメインレベルのCookieを表示できません。

ドメインレベルのCookieを使用して、同じドメイン内のサイト間でセッション情報を維持できます。

ドメインレベルのCookieをどのように設定するかは、開発環境によって異なります(Railsの経験はありません。申し訳ありません)。

1
Evan

ASP.NETを使用していますか?その場合は、 enableCrossAppRedirects プロパティを確認することをお勧めします。

1
Adrian Grigore

このソリューションでは、パスポートサーバーは必要ありません。

サインイン

  1. ログインする
  2. 暗号化されたセッションIDおよびその他の情報を使用してトークンを作成します
  3. Cookieを設定するために、すべてのドメインのトークンを含むimgを表示します。

クッキーによる承認

  1. すでにすべてのドメインにCookieがあります。

サインアウト

  1. クリアクッキー
  2. セッションを破棄する
  3. DB内の最後のセッションIDとの関係ユーザーIDをクリアします(Cookieによってセッションを立ち上げるためにセッションIDをユーザーテーブルに保存すると思います)

私はこの解決策を試すことができません。しかし今、私はあなた(SSO)と同じ問題を抱えており、明日これを試します。

1
Ivan Shumkov

SSOシナリオとフェデレーションIDの両方にシボレスを使用しましたが、上記よりも単純なソリューションが必要だと思います。

0