3

ユーザーに特定のサービスを提供する Web サイト .NET を作成しています。service1.com としましょう。将来的には、service2.com があり、データベースを共有します。また、ユーザーが Google などに登録していない場合に備えて、Google、Facebook、Twitter でのログイン + カスタム サインアップを提供することで、ユーザー フレンドリーな認証を行いたいと考えています。DotNetOpenAuthライブラリを使用します。したがって、シナリオはSOに似ています。

現在、Googleには差し迫った問題があります。異なる領域に対して異なる主張された識別子を提供します。つまり、ユーザーのIDとして使用することはできませんが、ユーザーを解決するために電子メールを画像に追加する必要があります( SOが行っているように)。

それに加えて、Facebook Connect、Twitter、およびすべてのサービス サイトのすべての追加ログイン オプションをサポートする必要があることを意味します。

そこで、OpenID プロキシのアイデアを思いつきました。

  • OpenID プロバイダー openid.service.com を独自の別のデータベースで作成します
  • service1.com と service2.com はその証明書利用者であり、独自のデータベースを共有しています
  • openid.service.com は、さまざまな方法でユーザーを認証できます。
  • ログイン オプションとサインアップ フォームは、すべてのサービス Web サイトの iframe に表示されます (SO サインアップのように)
  • openid.service.com がオプションのいずれかによってユーザーを認証すると、要求された識別子を証明書利用者のコールバックに提供します

したがって、最終結果は次のようになります。ここに画像の説明を入力

長所:

  • サービスは、openid.service.com から提供された要求された識別子を使用して、ログインしているユーザーを識別できます
  • 必要なドメインに簡単にサービスを追加できます
  • openid.service.comが処理するため、ログインオプションを追加するのは簡単です
  • openid.service.com が認証を処理するため、Google が主張する識別子は変更されません

短所:

  • 認証チェーンが長くなります (サービスは Google などで直接認証されません)。
  • ???

これはそのようなシステムを実装する適切な方法ですか?これには追加の欠点がありますか?

4

1 に答える 1

2

はい、それはこの問題を解決する合理的な方法です。実際、StackOverflow も同じことをしていると思います。OpenID を使用していないユーザー向けのカスタム ユーザー データベースも openid.service.com にあるため、実際にはその場合でも OpenID を使用していることになりますが、彼らはそれを知りません。

注意すべきことの 1 つは、あなたの例の openid.service.com は、 Google などからの元の主張された識別子をアサートできないことです。これは、主張された ID に対する権限がないため、セカンダリ RP が仲介者からのアサーションを受け入れないためです。 . 代わりに、openid.service.com と各補助 RP の間で認証なしのOpenID を使用できます。はい、実際には、OpenID には、OP から RP に渡される要求された識別子がなく、拡張のみのフローがあります。したがって、DotNetOpenAuthFetchRequestFetchResponse拡張機能を使用して、補助 RP と中央サービスの間でユーザーの実際の claim_id を要求できます。そして、補助 RP は非常に中央の RP からのアサーションのみを受け入れるように注意してください。

以下は、補助 RP と中央の RP の間のコードのスケッチです。

ステップ 1: RP が openid.service.com からユーザーの認証を要求する

OpenIdRelyingParty rp;
var request = rp.CreateRequest("https://openid.service.com/");
request.IsExtensionOnly = true;
var fetchRequest = new FetchRequest();
fetchRequest.Attributes.AddRequired("http://openid.service.com/useridentity");
request.AddExtension(fetchRequest);
request.RedirectToProvider();

ステップ 2: OP として機能する openid.service.com がリクエストを受け取ります (OP であることは大きな責任です... これは、すべてのアカウントで非常に不完全なサンプルです。利用可能な OpenIdProvider サンプルを参照する必要があります。)

OpenIdProvider op;
IRequest request = op.GetRequest();
/// ...
IAnonymousRequest anonRequest = request as IAnonymousRequest;
if (anonRequest != null) {
    // The key part for this sample snippet is that you make sure the RP asking
    // is one of your own, since you're not following the typical OpenID flow.
    if (!IsWhiteListedRealm(hostRequest.Realm)) {
        anonRequest.IsApproved = false; // reject all RPs that aren't in the whitelist
    } else {
        // Perhaps here is where you'll start your double role as an RP
        // to authenticate the user if there isn't already a FormsAuth cookie.
    }
}

return op.PrepareResponse(request).AsActionResult()

ステップ 3: 補助 RP がプロキシ OpenID サービスから応答を受信します。

OpenIdRelyingParty rp;
var response = rp.GetResponse();
if (response != null) {
    if (response.Provider.Uri.Authority != "openid.service.com") {
        throw new Exception(); // only assertions from our own OP are trusted.
    }

    if (response.Status == AuthenticationStatus.ExtensionsOnly) {
        var fetchResponse = response.GetExtension<FetchResponse>();
        string claimedId = fetchResponse.GetAttributeValue("http://openid.service.com/useridentity");
        FormsAuthentication.RedirectFromLoginPage(claimedId);
    }
}

これらのサンプルは完全ではありません。また、上記は、これらの役割を果たしている Web サイトの通常のセキュリティ対策の多くを適用しません。これは、特定の状況でアプリが実行する必要がある追加の手順の概要を示す単なるスケッチです。

于 2013-03-24T14:03:54.477 に答える