J'ai récemment commencé à regarder le nouveau cadre d'identité ASP.Net et le middleware Katana, il y a une quantité surprenante de code et de documentation, mais je vois ce qui semble être beaucoup d'informations contradictoires, ce qui, je suppose, est un résultat de la fréquence croissante des mises à jour du code.
Je cherche à utiliser l'authentification WsFederation contre un service ADFS 2 interne, mais la façon dont fonctionne le pipeline d'authentification OWIN me laisse un peu perplexe et j'espère que quelqu'un pourra en proposer définitif informations.
Plus précisément, je suis intéressé par l'ordre dans lequel le middleware doit être connecté et les modules requis dans divers scénarios, je voudrais me débarrasser de tout ce qui n'a pas besoin d'être là et en même temps m'assurer que le processus est aussi sûr que possible.
Par exemple, il semblerait que UseWsFederationAuthentication
devrait être utilisé en conjonction avec UseCookieAuthentication
, mais je ne sais pas quel serait le AuthenticationType
correct ( this post suggère que ce n'est qu'une chaîne d'identifiant, mais sa valeur est-elle significative?) ou même si nous devons encore utiliser SetDefaultSignInAsAuthenticationType
.
J'ai également remarqué ce fil sur le forum de discussion du projet Katana, où Tratcher mentionne une erreur courante, mais n'est pas très précis quant à la partie du code qui est en erreur.
Personnellement, j'utilise maintenant ce qui suit (avec un gestionnaire de jeton SAML personnalisé pour lire la chaîne de jeton dans un document XML valide), cela fonctionne pour moi, mais est-ce optimal?
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
}
}
}
}
);
Merci beaucoup pour tout ce que vous pouvez offrir pour dissiper cette confusion pour moi.
Comme l'a dit @Tratcher, le paramètre AuthenticationType
est utilisé par Microsoft.Owin.Security
Comme clé pour effectuer des recherches d'instances de middleware d'authentification.
Le code ci-dessous utilisera la méthode d'assistance simple suivante pour exiger que toutes les demandes soient authentifiées. En pratique, vous êtes plus susceptible d'utiliser un attribut [Authorize]
Sur les contrôleurs sensibles, mais je voulais un exemple qui ne repose sur aucun framework:
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);
}
});
}
L'appel context.Authentication.Challenge(authenticationTypes)
lancera un défi d'authentification à partir de chacun des types d'authentification fournis. Nous allons simplement fournir celui, notre type d'authentification WS-Federation.
Donc, d'abord, voici un exemple de la configuration de démarrage Owin "optimale" pour un site qui utilise simplement WS-Federation, comme vous êtes:
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();
}
Notez l'utilisation de la "WS-Fed Auth (Primary)"
AuthenticationType
pour identifier de manière unique l'instance de middleware WS-Federation que nous avons configurée. Cela signifie que vous pourriez, par exemple, utiliser une "WS-Fed Auth (Secondary)"
avec un serveur WS-Federation distinct comme solution de rechange, si vous aviez cette exigence.
Cette configuration fera ce qui suit:
CookieAuthenticationDefaults
, et c'est la valeur par défaut utilisée par la propriété CookieAuthenticationOptions.AuthenticationType
.)AuthenticationType
que nous avons définie comme valeur par défaut à l'étape 1.Microsoft.Owin.Security
méthodes pour lancer des contestations à toute demande non authentifiée)Il y a donc deux façons de vous tromper ici.
Pour expérimenter, j'ai essayé de le faire, et vous verrez tout de suite quel est le problème:
public void Configuration(IAppBuilder app)
{
var x = app.GetDefaultSignInAsAuthenticationType();
app.SetDefaultSignInAsAuthenticationType(x);
}
Ce premier appel vous donnera l'exception que vous avez mentionnée dans votre premier commentaire:
"Une valeur par défaut pour SignInAsAuthenticationType est introuvable dans les propriétés IAppBuilder. Cela peut se produire si votre middleware d'authentification est ajouté dans le mauvais ordre, ou s'il en manque un."
Droite - parce que par défaut le pipeline Microsoft.Owin.Security
N'assume rien sur le middleware que vous allez utiliser (c'est-à-dire que Microsoft.Owin.Security.Cookies
N'est même pas connu pour être présent), donc il ne le fait pas ' Je ne sais pas quelle devrait être la valeur par défaut.
Cela m'a coûté beaucoup de temps aujourd'hui car je ne savais pas vraiment ce que je faisais:
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType("WS-Fed AAD Auth");
// ... remainder of configuration
}
Donc, cela va continuer d'essayer d'authentifier l'appelant avec WS-Federation à chaque appel. Ce n'est pas que c'est super cher, c'est que le WS- Le middleware de la fédération émettra un défi à chaque demande. Vous ne pourrez donc jamais entrer et vous verrez beaucoup d'URL de connexion passer devant vous . : P
Donc, ce qui est génial d'avoir toute cette flexibilité dans le pipeline, c'est que vous pouvez faire des choses vraiment cool. Par exemple, j'ai un domaine avec deux applications Web différentes à l'intérieur, fonctionnant sous différents sous-chemins comme: example.com/foo
Et example.com/bar
. Vous pouvez utiliser la fonctionnalité de mappage d'Owin (comme dans app.Map(...)
) pour configurer un pipeline d'authentification totalement différent pour chacune de ces applications. Dans mon cas, l'un utilise WS-Federation, tandis que l'autre utilise des certificats clients. Essayer de faire cela dans le cadre monolithique System.Web
Serait horrible. : P