web-dev-qa-db-ja.com

OWIN認証パイプライン、およびKatanaミドルウェアの正しい使用方法

私は最近、新しいASP.Net IdentityフレームワークとKatanaミドルウェアの検討を始めました。驚くべき量のコードとドキュメントがそこにありますが、多くの矛盾する情報と思われるものを見ています。コードの更新頻度の増加の結果。

私は内部ADFS 2サービスに対してWsFederation認証を使用したいと考えていますが、OWIN認証パイプラインの動作が少し混乱しているため、誰かがdefinitive情報。

具体的には、ミドルウェアを接続し、さまざまなシナリオで必要なモジュールの順序に興味があります。そこにある必要のないものはすべて取り除き、同時にプロセスは可能な限り安全です。

たとえば、UseWsFederationAuthenticationUseCookieAuthenticationと組み合わせて使用​​する必要があるように見えますが、正しいAuthenticationTypeがどうなるかわかりません( this postは、それが単なる識別子文字列であることを示唆していますが、それは重要な値ですか?)またはSetDefaultSignInAsAuthenticationTypeを使用する必要がある場合でも。

また、Tratcherがよくある間違いに言及しているが、コードのどの部分にエラーがあるかについてはあまり明確ではないKatana Projectディスカッションボードの this スレッドに気付きました。

個人的に、私は次を使用しています(トークン文字列を有効なXMLドキュメントに読み込むためのカスタムSAMLトークンハンドラーを使用)。

var appURI = ConfigurationManager.AppSettings["app:URI"];
var fedPassiveTokenEndpoint = ConfigurationManager.AppSettings["wsFederation:PassiveTokenEndpoint"];
var fedIssuerURI = ConfigurationManager.AppSettings["wsFederation:IssuerURI"];
var fedCertificateThumbprint = ConfigurationManager.AppSettings["wsFederation:CertificateThumbprint"];

var audienceRestriction = new AudienceRestriction(AudienceUriMode.Always);

audienceRestriction.AllowedAudienceUris.Add(new Uri(appURI));

var issuerRegistry = new ConfigurationBasedIssuerNameRegistry();

issuerRegistry.AddTrustedIssuer(fedCertificateThumbprint, fedIssuerURI);

app.UseCookieAuthentication(
    new CookieAuthenticationOptions
    {
        AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType // "Federation"
    }
);

app.UseWsFederationAuthentication(
    new WsFederationAuthenticationOptions
    {
        Wtrealm = appURI,
        SignOutWreply = appURI,
        Configuration = new WsFederationConfiguration
        {
            TokenEndpoint = fedPassiveTokenEndpoint
        },
        TokenValidationParameters = new TokenValidationParameters
        {
            AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
        },
        SecurityTokenHandlers = new SecurityTokenHandlerCollection
        {                        
            new SamlSecurityTokenHandlerEx
            {
                CertificateValidator = X509CertificateValidator.None,
                Configuration = new SecurityTokenHandlerConfiguration
                {
                    AudienceRestriction = audienceRestriction,
                    IssuerNameRegistry = issuerRegistry
                }
            }
        }
    }
);

この混乱を解決するためにあなたが提供できるものに感謝します。

34
Tom Tregenna

@Tratcherが言ったように、AuthenticationTypeパラメーターは_Microsoft.Owin.Security_によって認証ミドルウェアインスタンスの検索を行うためのキーとして使用されます。

以下のコードは、次の単純なヘルパーメソッドを使用して、all要求の認証を要求します。実際には、機密性の高いコントローラーで_[Authorize]_属性を使用する可能性が高くなりますが、フレームワークに依存しない例が必要でした。

_private static void AuthenticateAllRequests(IAppBuilder app, params string[] authenticationTypes)
{
    app.Use((context, continuation) =>
    {
        if (context.Authentication.User != null &&
            context.Authentication.User.Identity != null &&
            context.Authentication.User.Identity.IsAuthenticated)
        {
            return continuation();
        }
        else
        {
            context.Authentication.Challenge(authenticationTypes);
            return Task.Delay(0);
        }
    });
}
_

context.Authentication.Challenge(authenticationTypes)呼び出しは、提供された各認証タイプから認証チャレンジを発行します。 WS-フェデレーション認証タイプを提供するだけです。

正しいコード

したがって、最初に、WS-Federationを単純に使用しているサイトの「最適な」Owinスタートアップ構成の例を次に示します。

_public void Configuration(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions());

    app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
    {
        AuthenticationType = "WS-Fed Auth (Primary)",
        Wtrealm = ConfigurationManager.AppSettings["app:URI"],
        MetadataAddress = ConfigurationManager.AppSettings["wsFederation:MetadataEndpoint"]
    });

    AuthenticateAllRequests(app, "WS-Fed Auth (Primary)");

    app.UseWelcomePage();
}
_

"WS-Fed Auth (Primary)"AuthenticationTypeを使用して、構成したWS-Federationミドルウェアインスタンスを一意に識別することに注意してください。これは、たとえば、別のWSフェデレーションサーバーで"WS-Fed Auth (Secondary)"をフォールバックとして使用できることを意味します(要件がある場合)。

この構成は次のことを行います。

  1. 最初に、デフォルトでデフォルトのCookeAuthentication AthenticationType値でリクエストを認証することをOwinセキュリティパイプラインに伝えます。 (これはそのCookieAuthenticationDefaultsクラスの単なる定数文字列であり、_CookieAuthenticationOptions.AuthenticationType_プロパティで使用されるデフォルト値です。)
  2. 次に、すべてのデフォルトオプションでCookie認証ミドルウェアインスタンスを登録します。これにより、ステップ1でデフォルトとして設定したAuthenticationTypeキーに対応します。
  3. 次に、Web.configファイルで定義したオプションでWS-Federation認証ミドルウェアインスタンスを登録しますおよび後で参照できるようにカスタムAuthenticationType値を使用
  4. すべての認証ミドルウェアの登録が完了したら、パイプラインにallリクエストを認証するように指示します(認証されていないユーザーにチャレンジを発行するための_Microsoft.Owin.Security_メソッドを呼び出すカスタムヘルパーメソッドを介して)リクエスト)
  5. 最後に、ユーザーが認証されている場合、ようこそページを表示します!

不正なコード

したがって、ここでうまくいかない場合があるいくつかの方法があります。

デフォルトの認証タイプを提供しない

実験するために、これを試してみましたが、問題がすぐにわかります。

_public void Configuration(IAppBuilder app)
{
    var x = app.GetDefaultSignInAsAuthenticationType();

    app.SetDefaultSignInAsAuthenticationType(x);
}
_

最初の呼び出しでは、最初のコメントで言及した例外が表示されます。

「SignInAsAuthenticationTypeのデフォルト値がIAppBuilderプロパティで見つかりませんでした。これは、認証ミドルウェアが間違った順序で追加された場合、または見つからない場合に発生する可能性があります。」

右-デフォルトでは_Microsoft.Owin.Security_パイプラインは使用するミドルウェアについて何も想定していないため(つまり、_Microsoft.Owin.Security.Cookies_は存在することすら知られていないため)、デフォルトにすべきもの。

間違ったデフォルト認証タイプを使用する

私は自分が何をしていたのか本当にわからなかったので、今日はかなりの時間がかかりました。

_public void Configuration(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType("WS-Fed AAD Auth");

    // ... remainder of configuration
}
_

だから、それはすべての呼び出しでWS-Federationで呼び出し側を認証しようとし続けます。それはそれが非常に高価なことではなく、WS-Federationミドルウェアが実際にすべてのリクエストでチャレンジを発行します。だから、あなたは決して入ることができず、たくさんのログインURLがあなたを通り過ぎるのを見るでしょう。 :P

可能性

パイプラインにこのような柔軟性を持たせることの素晴らしい点は、本当にクールなことができるということです。たとえば、2つの異なるWebアプリが含まれるドメインがあり、_example.com/foo_と_example.com/bar_のような異なるサブパスで実行されています。 Owinのマッピング機能(app.Map(...)など)を使用して、これらのアプリごとにまったく異なる認証パイプラインを設定できます。私の場合、1つはWS-Federationを使用し、もう1つはクライアント証明書を使用しています。モノリシックな_System.Web_フレームワークでそれを行おうとするのは恐ろしいことです。 :P

49
Lars Kemmann