Pregunta La canalización de autenticación OWIN y cómo utilizar el middleware Katana correctamente?


Recientemente comencé a buscar en el nuevo marco de identidad ASP.Net y en el middleware Katana, hay una sorprendente cantidad de código y documentación, pero veo lo que parece ser una gran cantidad de información conflictiva, que supongo que es una resultado de la creciente frecuencia de actualizaciones de código.

Estoy buscando utilizar la Autenticación WsFederation contra un servicio interno ADFS 2, pero la forma en que funciona la canalización de autenticación OWIN me tiene un poco confundido y espero que alguien pueda ofrecer algunos definitivo información.

Específicamente, estoy interesado en el orden en que se debe conectar el middleware y qué módulos se requieren en varios escenarios, me gustaría deshacerme de todo lo que no necesita estar allí y al mismo tiempo asegurarme de que proceso es lo más seguro posible.

Por ejemplo, parece que UseWsFederationAuthentication debe usarse junto con UseCookieAuthentication, pero no estoy seguro de cuál es la correcta AuthenticationType sería (esta publicación sugiere que es solo una cadena de identificador, pero ¿es significativo su valor?) o incluso si aún necesitamos usar SetDefaultSignInAsAuthenticationType.

También noté esta hilo en el tablero de discusión del Proyecto Katana, donde Tratcher menciona un error común, pero no es muy específico en cuanto a qué parte del código es errónea.

Personalmente, ahora estoy usando lo siguiente (con un gestor de tokens de SAML personalizado para leer la cadena de tokens en un documento XML válido), funciona para mí, pero ¿es óptimo?

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
                }
            }
        }
    }
);

Muchas gracias por todo lo que puede ofrecer para ayudar a aclarar esta confusión para mí.


32
2017-09-04 10:59


origen


Respuestas:


Como dijo @Tratcher, el AuthenticationType parámetro es utilizado por Microsoft.Owin.Security como una clave para realizar búsquedas de instancias de middleware de autenticación.

El siguiente código usará el siguiente método de ayuda simple para requerir que todas las solicitudes están autenticadas En la práctica, es más probable que use un [Authorize] atributo en controladores sensibles, pero quería un ejemplo que no dependa de ningún marco:

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);
        }
    });
}

los context.Authentication.Challenge(authenticationTypes) la llamada emitirá un desafío de autenticación de cada uno de los tipos de autenticación proporcionados. Solo vamos a proporcionar uno, nuestro tipo de autenticación WS-Federation.

Código correcto

Primero, aquí hay un ejemplo de la configuración de inicio de Owin "óptima" para un sitio que simplemente usa WS-Federation, como usted:

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();
}

Tenga en cuenta el uso de la "WS-Fed Auth (Primary)"  AuthenticationType para identificar de manera única la instancia de middleware de WS-Federation que hemos configurado. Esto significa que podría, por ejemplo, usar un "WS-Fed Auth (Secondary)" con un servidor separado WS-Federation como alternativa, si tuviera ese requisito.

Esta configuración hará lo siguiente:

  1. En primer lugar, indique a la cartera de seguridad de Owin que, de forma predeterminada, queremos autenticar las solicitudes con el valor predeterminado de CookeAuthentication AthenticationType. (Eso es solo una cadena constante en eso CookieAuthenticationDefaults clase, y es el valor predeterminado utilizado por el CookieAuthenticationOptions.AuthenticationTypepropiedad.)
  2. A continuación, registre una instancia de middleware de autenticación de cookies con todas las opciones predeterminadas, por lo que corresponde a la AuthenticationType clave que configuramos como predeterminada en el paso 1.
  3. A continuación, registre una instancia de middleware de autenticación de WS-Federation con las opciones que definimos en el archivo Web.config, y con un valor de AuthenticationType personalizado para que podamos consultarlo más tarde.
  4. Después de que se hayan realizado todos los registros de middleware de autenticación, le indicamos a la tubería que se autentique. todas solicitudes (a través de nuestro método de ayuda personalizado que llama al Microsoft.Owin.Security métodos para emitir impugnaciones a cualquier solicitud no autenticada)
  5. Finalmente, si el usuario ha sido autenticado, ¡muestre la página de bienvenida!

Codigo erroneo

Entonces hay un par de formas en que puedes equivocarte aquí.

No proporciona un tipo de autenticación predeterminado

Para experimentar, intenté hacer esto, y verás de inmediato cuál es el problema:

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

    app.SetDefaultSignInAsAuthenticationType(x);
}

Esa primera llamada le dará la excepción que mencionó en su primer comentario:

"No se encontró un valor predeterminado para SignInAsAuthenticationType en las propiedades de IAppBuilder. Esto puede suceder si su middleware de autenticación se agrega en el orden incorrecto o si falta uno".

Derecha - porque por defecto el Microsoft.Owin.Security pipeline no asume nada sobre el middleware que va a utilizar (es decir, Microsoft.Owin.Security.Cookies ni siquiera se sabe que esté presente), por lo que no sabe cuál debería ser el valor predeterminado.

Usar el tipo de autenticación predeterminado incorrecto

Esto me costó mucho tiempo hoy porque realmente no sabía lo que estaba haciendo:

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

    // ... remainder of configuration
}

Entonces, eso intentará seguir autenticando a la persona que llama con WS-Federation en cada llamada. No es tan caro, es que el middleware WS-Federation en realidad Emitir un desafío en cada solicitud. Entonces, no puedes entrar, y ves que muchas URL de inicio de sesión pasan volando. :PAG

Posibilidades

Entonces, lo bueno de tener toda esta flexibilidad en la tubería es que puedes hacer cosas realmente geniales. Por ejemplo, tengo un dominio con dos aplicaciones web diferentes dentro de él, que se ejecuta en diferentes subcampos como: example.com/foo y example.com/bar. Puede usar la funcionalidad de mapeo de Owin (como en app.Map(...)) para configurar una canalización de autenticación totalmente diferente para cada una de esas aplicaciones. En mi caso, uno usa WS-Federation, mientras que el otro usa certificados de cliente. Intentando hacer eso en el monolítico System.Web el marco sería horrible :PAG


46
2017-10-08 20:23