Partager via


Cet article a fait l'objet d'une traduction automatique.

Identité fédérée

Authentification passive pour ASP.NET avec WIF

Michele Leroux Leroux

L'objectif de sécurité fédérée est de fournir un mécanisme pour établir des relations d'approbation entre domaines pour que les utilisateurs peuvent authentifier vers leur propre domaine, tout en étant autorisé à accéder aux applications et services qui appartiennent à un autre domaine. Cela permet de techniques d'authentification tels que l'ouverture de session unique, supprime la nécessité de configurer et gérer des comptes dupliqués pour les utilisateurs sur plusieurs applications et les domaines et réduit considérablement le coût d'étendre les applications à des parties de confiance.

Dans un modèle de sécurité fédérée, un fournisseur d'identité (IdP) effectue l'authentification et fournit un service STS (Security Token) pour les jetons de sécurité de problème. Ces jetons, à son tour, d'informations sur l'utilisateur authentifié d'assertion : son identité (et éventuellement d'autres informations, y compris des rôles et des droits d'accès plus granulaires. Dans un environnement fédéré, ces informations sont appelées créances et contrôle d'accès basé sur les revendications est central pour un modèle de sécurité fédérée. Dans ce modèle, les applications et services autorisent l'accès aux fonctions et fonctionnalités basées sur les revendications d'émetteurs approuvés (SharePoint Team Services).

Les outils de plateforme tels que Windows Identity Foundation (WIF) facilitent nettement la prise en charge de ce type de fédération d'identité. WIF est une structure de modèle d'identité pour la création d'applications basées sur des déclarations et des services et de prise en charge SOAP (actif) et les scénarios de fédération de (passif) à partir d'un navigateur. Dans l'article “ autorisation basée sur les revendications avec WIF , ” dans le numéro de 2009 de novembre du MSDN Magazine, je me suis concentré sur l'utilisation de WIF avec Windows Communication Foundation (WCF). Dans cet article, j'ai décrit comment implémenter des modèles de sécurité basée sur des déclarations pour les services WCF et comment effectuer une migration pour la fédération d'identité.

Dans cet article de suivi, je me concentrerai sur la fédération passive. Je va expliquer le flux de communication pour la fédération passive, vous montrent différentes techniques permettant d'activer la fédération dans vos applications ASP.NET, discuter des techniques d'autorisation basée sur des déclarations pour ASP.NET et parler des scénarios de déconnexion de session et unique unique. J'expliquerai tout au long du processus, les fonctions WIF sous-jacentes et les composants qui prennent en charge des scénarios de fédération de passif.

Concepts de base du Federation passive

Scénarios de fédération passif sont basés sur la spécification WS-Federation. Ce document décrit comment demander des jetons de sécurité et la publication et d'acquérir des documents de métadonnées de la fédération, qui facilite la mise en place les relations d'approbation. WS-Federation décrit également les procédures de connexion et déconnexion unique et d'autres concepts de mise en œuvre de la fédération.

Tandis que WS-Federation présente les nombreux détails à propos de la fédération, sections sont consacrées à la fédération étendue à partir d'un navigateur qui s'appuient sur le verbe HTTP GET et POST, les redirections de navigateur et les cookies pour atteindre l'objectif.

Certains aspects de la messagerie de la fédération passive sont en étroite collaboration basées sur la spécification WS-Trust. Par exemple, la fédération passive a recours à un formulaire compatible avec les navigateurs de Request Security Token (RST) et de réponse RST (RSTR) lorsqu'un jeton de sécurité est demandé d'un STS. Dans le scénario de fédération de passif, j'appellerai le RST un message de demande de connexion et le message de réponse RSTR sign-in. La spécification WS-Trust se concentre sur la fédération (active) basés sur SOAP, par exemple entre les clients Windows et les services WCF.

Un scénario simple de la fédération passif est illustré dans les de la figure 1 .

image: A Simple Passive Federation Scenario

Figure 1 simple scénario de fédération de passif une

Les utilisateurs authentifient à leur domaine et autorisés à accéder à une application Web en fonction de leurs rôles. Les participants de ce schéma d'authentification comprennent l'utilisateur (le sujet), un navigateur Web (le demandeur), une application ASP.NET (la partie utilisatrice ou RP), un IdP chargé d'authentifier les utilisateurs au sein de son domaine et qu'un STS appartenant au domaine de l'utilisateur (STS IP). Une séquence de redirections du navigateur garantit que l'utilisateur est authentifié à son domaine avant de l'accès au RP.

L'utilisateur accède à l'application du RP (1) et est redirigé vers son IdP pour être authentifié (2). Si l'utilisateur n'a pas encore été authentifié à la IdP, l'IP/STS peuvent présenter un défi ou lui Rediriger vers une page de connexion pour collecter des informations d'identification (3). L'utilisateur fournit ses informations d'identification (4) et est authentifié par le SJS de IP (5). À ce stade, l'IP/STS émet un jeton de sécurité en fonction de la demande de connexion et la réponse de contenant le jeton est validée vers le RP via une redirection du navigateur (6). Le RP traite le jeton de sécurité et autorise l'accès basé sur les revendications qu'il exécute (7). Si autorisé avec succès, l'utilisateur voit s'afficher la page qu'a demandé à l'origine et un cookie de session est renvoyé (8).

Mise en œuvre ce scénario de fédération passif avec WIF et ASP.NET implique quelques étapes :

  1. Établir une relation d'approbation entre le RP et IdP (STS IP)
  2. Activer la fédération passive de l'application ASP.NET
  3. L'autorisation de mettre en œuvre vérifie pour contrôler l'accès aux fonctionnalités de l'application dans les sections suivantes, que j'aborderai les fonctionnalités de WIF qui prennent en charge de la fédération passive, passez en revue les étapes de configuration de ce scénario simple et ensuite Explorer les autres considérations pratiques pour les autres scénarios.

Fonctionnalités WIF pour la fédération passive

Avant d'aborder l'implémentation, je vais passer en revue les fonctionnalités de WIF plus particulièrement utile pour la fédération d'identité dans vos applications ASP.NET. Dans un premier temps, WIF fournit les modules HTTP utiles suivants :

  • WSFederationAuthenticationModule (FAM) : Permet de fédération à partir d'un navigateur, la redirection vers le SJS approprié pour l'authentification et d'émission de jeton de traitement et de traitement de la réponse de connexion résultante à d'hydrates le jeton de sécurité émis dans un ClaimsPrincipal pour être utilisé pour l'autorisation. Ce module traite également les autres messages de la fédération importantes telles que des demandes de déconnexion.
  • SessionAuthenticationModule (SAM) : Gère la session authentifiée en générant le jeton de sécurité de session qui contient le ClaimsPrincipal, écrire dans un cookie, gestion de la durée de vie du cookie de session et réalimentation le ClaimsPrincipal à partir du cookie lorsqu'il est présenté. Ce module gère également un cache de jetons de session locale.
  • ClaimsAuthorizatonModule : Fournit un point d'extensibilité pour installer un ClaimsAuthorizationManager personnalisé qui peut être utile pour les vérifications d'accès centralisée.
  • ClaimsPrincipalHttpModule : Crée un ClaimsPrincipal à partir de l'identité de l'utilisateur en cours attachée au thread de demande. En outre, fournit un point d'extensibilité pour installer un ClaimsAuthenticationManager personnalisé qui peut être utile pour la personnalisation ClaimsPrincipal pour être attaché au thread de demande.

ClaimsPrincipalHttpModule est particulièrement utile pour les applications sans fédération passive. Vous pouvez considérer cela comme un outil utile pour implémenter un modèle de sécurité basée sur les revendications dans l'application ASP.NET avant de passer à la fédération passive. J'ai abordé cette technique pour WCF dans mon article précédent.

Les trois autres modules sont généralement utilisées ensemble pour la fédération passive — ClaimsAuthorizationModule est facultative. La figure 2 illustre comment ces principaux modules s'intègrent dans le pipeline de requêtes et leur fonction dans une requête d'authentification fédéré typique.

image: WIF Components and HTTP Modules Engaged in Passive Federation

La figure 2 WIF Components and HTTP modules engagés dans Federation Passive

En gardant à l'esprit le flux de la fédération passive à partir de de figure 1, lorsque l'utilisateur accède pour la première fois à une page protégée, dans le RP (1), l'accès à la demande sera refusée. Le FAM traite les demandes non autorisées, génère le message d'authentification et redirige l'utilisateur vers le SJS de IP (2). L'IP/STS authentifie l'utilisateur (3), génère une réponse d'authentification qui inclut le jeton de sécurité émis et la redirige vers l'application de RP (4).

Le FAM traite la réponse de connexion, garantissant ainsi que la réponse contienne un jeton de sécurité valide de l'utilisateur authentifié et hydrates un ClaimsPrincipal à partir de la connexion, dans la réponse (5). Ceci définit l'entité de sécurité pour la thread de demande et l'objet HttpContext. Le FAM utilise ensuite le Gestionnaire SAM de sérialiser les revendications du ­ principal à un cookie HTTP (6) qui s'affiche avec les demandes suivantes au cours de la session du navigateur. Si ClaimsAuthorizationModule est installé, il invoquera ClaimsAuthorization configuré ­ Gestionnaire, offrant la possibilité d'effectuer un accès ininterrompu vérifie (7) par rapport à la ClaimsPrincipal avant d'accéder à la ressource demandée.

Une fois que la ressource demandée est présentée, contrôle d'accès peut être implémenté avec les contrôles de connexion ASP.NET traditionnels, le contrôle IsInRole et tout autre code personnalisé qui interroge l'utilisateur plaint (8).

Pour les demandes suivantes, le jeton de session est présenté avec le cookie écrit précédemment par le SAM (9). Cette fois le Gestionnaire SAM est activé pour valider le jeton de session et de réalimenter les revendications du ­ principal à partir du jeton (10). Le FAM n'est pas activé, sauf si la demande est une réponse de signe, une demande de déconnexion, ou si l'accès est refusé, ce qui peut se produire si le jeton de session n'est pas présent ou est arrivé à expiration.

Outre ces modules, il existe deux contrôles ASP.NET qui sont également utiles pour la fédération passive :

  • Contrôle FederatedPassiveSignIn : Peut être utilisé à la place de la FAM si l'application redirige tous les appels non autorisés pour une page de connexion qui héberge ce contrôle uniquement lorsque l'authentification est requise. Cela suppose que l'utilisateur interagit avec le signe-processus, utiles dans les scénarios d'authentification croissante lorsque l'utilisateur est invité pour les informations d'identification, peut-être plues d'informations d'identification à partir de la connexion d'accès d'origine, comme requis par l'application. Le contrôle gère la redirection vers le SJS, traitement de la réponse de connexion, lors de l'initialisation du ClaimsPrincipal à partir de la réponse et l'établissement d'une session sécurisée en tirant parti des fonctionnalités exposées par la FAM et SAM.
  • Contrôle FederatedPassiveSignInStatus : Ce contrôle fournit un moyen interactif de l'utilisateur à ouvrir une session ou signe plus à partir de l'application de RP, y compris la prise en charge de fédérés déconnexion.

La figure 3 illustre comment le flux de communication change lorsque le contrôle FederatedPassiveSignIn est employé. L'application s'appuie sur l'authentification par formulaires pour protéger les ressources et de rediriger vers la page de connexion d'accès, qui héberge le contrôle (1). L'utilisateur clique sur le contrôle FederatedPassiveSignIn (ou peut être redirigé automatiquement vers elle), qui déclenche une redirection vers le SJS (2). La page du contrôle reçoit la réponse le SJS, en se basant sur le FAM et le Gestionnaire SAM pour traiter la réponse de connexion (3), d'hydrates le ­ de revendications principal et écrire le cookie de session (4). Lorsque l'utilisateur est redirigé vers la page initialement demandée (5), le Gestionnaire SAM est engagé à valider le cookie de session et d'hydrates le ClaimsPrincipal pour la demande. À ce stade, le ClaimsAuthorizationModule et cette page peuvent effectuer leurs contrôles d'autorisation, comme illustré dans les de la figure 2 .

image: Passive Federation with the FederatedPassive­-SignIn Control

La figure 3 Fédération de passive avec le FederatedPassive ­-contrôle de l'ouverture de session

Le FAM et le SAM dépendent de la sécurité appropriée ­ type TokenHandler pour traiter les jetons d'entrants. Lors de l'arrivée d'une réponse de connexion, le FAM effectue une itération dans SecurityTokenHandlerCollection recherche pour le Gestionnaire de jeton approprié pour lire le jeton XML. Dans un scénario fédéré, il s'agit généralement de Saml11Security ­ TokenHandler ou Saml2Security ­ TokenHandler — bien que les autres formats de jetons peuvent être utilisées si vous ajoutez des gestionnaires de jetons personnalisés. Pour le SAM SessionSecurity ­ TokenHandler est utilisé pour traiter le jeton de session associé avec le cookie de session.

Plusieurs paramètres de configuration de modèle d'identité sont importants pour le flux de fédération de passif et sont utilisés pour initialiser la FAM et le SAM et le contrôle FederatedPassiveSignIn (bien que ce dernier expose également des propriétés configurables à partir du concepteur Visual Studio). Par programme, vous pouvez fournir une instance de la ­ de la service de type de configuration à partir de l'espace de noms Microsoft.IdentityModel.Configuration, ou vous pouvez fournir la configuration déclarative dans la section <microsoft.identityModel>. La figure 4 résumé des paramètres de modèle d'identité qui seront traitées dans les sections suivantes.

La figure 4 Résumé de l'essentiel <microsoft.identityModel> éléments

Section Description
<issuerNameRegistry> Spécifier une liste d'émetteurs de certificats de confiance. Cette liste est essentiellement utile pour la validation de la signature de jeton pour que les jetons signés par des certificats non approuvés seront rejetées.
<audienceUris> Spécifier une liste d'audience valide les URI pour les jetons SAML entrants. Peut être désactivée pour permettre à n'importe quel URI, mais ne pas recommandé.
<securityTokenHandlers> Personnaliser les paramètres de configuration pour les gestionnaires de jetons ou fournir des gestionnaires personnalisés de jetons pour contrôler comment les jetons sont validées, authentifiées et sérialisés.
<maximumClockSkew> Régler la différence de temps autorisé entre les jetons et les serveurs d'applications pour le jeton de validité. La valeur par défaut maximal autorisé est de 5 minutes.
<certificateValidation> Contrôler la façon dont les certificats sont validés.
<serviceCertificate> Fournir un certificat de service pour le décryptage de jetons entrants.
<claimsAuthenticationManager> Fournir un type ClaimsAuthenticationManager personnalisé pour personnaliser ou de remplacer le type IClaimsPrincipal pour être attaché au thread de demande.
<claimsAuthorizationManager> Fournir un type ClaimsAuthorizationManager personnalisé pour contrôler l'accès à la fonctionnalité à partir d'un composant central.
<federatedAuthentication> Fournir des paramètres spécifiques à la fédération passive.

Activation de la fédération passive

WIF rend facile à configurer la fédération passive pour vos applications ASP.NET. Un STS doit fournir des métadonnées de la fédération (comme décrit dans la spécification WS-Federation) et WIF fournit une fédération Utility (FedUtil.exe), qui utilise les métadonnées de la fédération pour établir une approbation entre un RP et un STS (parmi d'autres fonctionnalités utiles pour les deux scénarios de fédération active et passive). Vous pouvez appeler FedUtil à partir de la ligne de commande ou de Visual Studio en cliquant du bouton droit sur le projet RP et en sélectionnant Ajouter un STS référence.

Vous allez effectuer les étapes de simples suivantes avec l'Assistant FedUtil :

  • La première page de l'Assistant permet de confirmer le fichier de configuration pour être modifié par l'Assistant et l'URI d'application RP.
  • La deuxième page demande le chemin d'accès au document XML de métadonnées de la fédération pour le SJS que le RP établir l'approbation.
  • La troisième page permet de fournir un certificat à utiliser pour décrypter les jetons.
  • La dernière page affiche une liste de déclarations offertes par le SJS, qui vous permet de planifier les décisions de contrôle d'accès, par exemple.

Une fois terminées les étapes de l'Assistant, FedUtil modifie le projet pour ajouter une référence à l'assembly Microsoft.IdentityModel. En outre, il modifie le fichier web.config pour installer les modules FAM et SAM et fournir des paramètres de configuration de modèle d'identité de ces modules. Maintenant, l'application prend en charge de la fédération passive et redirige les demandes non autorisées pour le SJS de confiance.

Il existe une hypothèse ici que le SJS a une connaissance préalable du RP et va donc émettre des jetons pour les utilisateurs authentifiés, essayez d'accéder le RP et bien sûr qu'il a la clé publique du RP nécessite le SJS à utiliser pour crypter les jetons. Il s'agit d'un moyen simple d'obtenir vos applications ASP.NET configurées initialement pour la fédération. Bien sûr, il est utile de savoir cela définir à partir de zéro en cas d'ajustements sont nécessaires et dépassent les paramètres de base activées par l'Assistant. Je me concentrerai sur l'approche “ à partir de zéro ” à partir d'ici sur de.

Sans utiliser FedUtil, vous devez ajouter manuellement une référence à l'assembly Microsoft.IdentityModel et configurer manuellement le FAM et les modules de SAM avec les paramètres de modèle d'identité nécessaires. Les modules HTTP sont ajoutés aux deux sections : System.Web pour Internet Information Services (IIS) 6 et System.WebServer pour IIS 7. En supposant que l'application est hébergée dans IIS 7.0, les modules WIF sont configurées comme suit :

<modules>
  <!--other modules-->
  <add name="SessionAuthenticationModule" 
    type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
    preCondition="managedHandler" />
  <add name="WSFederationAuthenticationModule" 
    type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
    preCondition="managedHandler" />
</modules>

Par défaut cette configuration protégera uniquement les ressources avec les extensions mappées explicitement pour être gérées par le pipeline ASP.NET (.aspx, .asax, etc.). Pour protéger des ressources supplémentaires avec l'authentification fédérée, vous devez mapper les extensions pour le pipeline ASP.NET dans IIS, ou vous pouvez définir runAllManagedModulesForAllRequests sur true dans les modules Définition (IIS 7.0 uniquement) comme suit :

<modules runAllManagedModulesForAllRequests="true">

Pour FAM Démarrer, vous devez également définir le mode d'authentification ASP.NET sur aucun et refuser aux utilisateurs anonymes l'accès aux ressources d'application :

<authentication mode="None" />

<authorization>
  <deny users="?" />
</authorization>

Les deux modules dépendent des paramètres de configuration de modèle d'identité décrits dans les de la figure 4 , un exemple typique de qui est affiché dans les figure 5 . La plupart de ces paramètres est générée pour vous par FedUtil, à l'exception de certificateValidation et quelques exemples des paramètres au sein de federatedAuthentication. Je recommande généralement l'utilisation du mode de validation de certificat PeerTrust — c'est-à-dire que vous ajoutez explicitement tous les certificats, y compris celui de l'émetteur de confiance, à TrustedPeople banque l'ordinateur local de confiance.

La figure 5 de la Configuration de modèle d'identité pour la fédération passive

<microsoft.identityModel>
  <service>
    <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <trustedIssuers>
        <add thumbprint="EF38A0A6D1274766093D3D78BFE4ECA77C62D5C3" 
          name="http://localhost:60768/STS/" />
      </trustedIssuers>
    </issuerNameRegistry>
    <certificateValidation certificateValidationMode="PeerTrust" 
      revocationMode="Online" trustedStoreLocation="LocalMachine"/>
    <audienceUris>
      <add value="http://localhost:50652/ClaimsAwareWebSite2/" />
    </audienceUris>
    <federatedAuthentication>
      <wsFederation passiveRedirectEnabled="true" 
        issuer="http://localhost:60768/STS/" 
        realm="http://localhost:50652/ClaimsAwareWebSite2/" 
        requireHttps="true" />
      <cookieHandler requireSsl="true" name="FedAuth"  
        hideFromScript="true" path="/ClaimsAwareWebSite2" />
    </federatedAuthentication>
    <serviceCertificate>
      <certificateReference x509FindType="FindByThumbprint" 
        findValue="8A90354199D284FEDCBCBF1BBA81BA82F80690F2" 
        storeLocation="LocalMachine" storeName="My" />
    </serviceCertificate>
  </service>
 </microsoft.identityModel>

Vous devez en général nécessitent HTTPS/SSL pour la fédération passive afin de protéger le jeton émis PORTEUR contre les attaques de man-in-the-middle et nécessitent HTTPS/SSL pour les cookies de session. Par défaut, les cookies sont masqués à partir du script, mais il s'agit d'un paramètre important, c'est pourquoi je le souligner dans de la figure 5 .

Comme pour le nom et le chemin d'accès du cookie, le nom par défaut FedAuth, le chemin d'accès au répertoire d'application. Il peut être utile spécifier un nom unique pour le cookie, en particulier si de nombreuses applications RP dans la solution partagent le même domaine. À l'inverse, vous pouvez choisir de spécifier un chemin d'accès générique lorsque vous souhaitez que les cookies soient partagés par plusieurs applications sur le même domaine.

Vous allez généralement FedUtil permet de configurer vos applications ASP.NET pour la fédération passive à l'aide de la FAM et SAM, puis modifier les paramètres appropriés, conformément aux exigences de la solution. Vous pouvez également utiliser le contrôle PassiveFederationSignIn que du FAM comme illustré dans les de la figure 3 . Le contrôle peut soit charger de ses paramètres à partir de la section microsoft.identityModel, ou vous pouvez définir des propriétés directement sur le contrôle.

L'approche du contrôle est utile si vous souhaitez que les demandes non autorisées d'être redirigé vers une page de connexion dans laquelle l'utilisateur peut explicitement reconnectez-vous en cliquant sur le contrôle, plutôt que de devoir le FAM rediriger automatiquement vers le SJS. Par exemple, si l'utilisateur ne peut appartenir à plus d'un fournisseur d'identité (domaine d'origine), la page de connexion peut fournir un mécanisme pour lui indiquer son domaine associé avant de la redirection vers le SJS. J'aborderai bientôt découverte de domaine d'origine.

Émission de jeton passif

Comme mentionné précédemment, la fédération passive s'appuie sur les redirections HTTP GET et POST et le navigateur pour faciliter la communication entre le RP et SharePoint Team Services. La figure 6 affiche les paramètres de la demande principale impliqués dans la demande de connexion et de la réponse de connexion au cours du processus.

image: Primary Sign-In Request and Response Parameters Involved in Passive Federation Requests

La figure 6 principal Sign-in de demande et des paramètres de réponse impliqués dans les demandes de Federation Passive

Lorsque le SJS reçoit la demande de connexion, il vérifie qu'il connaît le RP en vérifiant le paramètre wtrealm par rapport à sa liste de domaines RP connus. Vraisemblablement, le SJS aura une connaissance préalable du RP, le certificat requis pour le jeton de chiffrement et les attentes par rapport aux déclarations de votre choix à inclure dans le jeton émis. Le RP peut indiquer qui prétend qu'il nécessite si elle fournit le paramètre facultatif wreq avec une demande d'authentification complet et le SJS peut éventuellement respecter cette liste ou sélectionner autonome qui prétend accorder en fonction de l'utilisateur authentifié.

Dans un scénario de fédération simple comme que décrit dans la section de la figure 1 , il existe un seul RP et un STS de IP unique chargé d'authentifier les utilisateurs. Si l'IP/STS authentifie les utilisateurs par rapport à un domaine Windows, il peut émettre un rôle de créances tels que Admin, User ou invité. Il est supposé que ces rôles ont une signification pour le RP pour l'autorisation. Dans la section suivante, je supposerai que ces rôles suffisant et discuter des techniques d'autorisation. Après que j'aborderai la transformation de déclarations au RP pour convertir les déclarations de SharePoint Team Services en quelque chose de plus utile pour l'autorisation en fonction des besoins.

Autorisation basée sur les revendications

Comme j'ai abordé dans mon article précédent, basée sur les rôles sécurité dans le .NET Framework s'attend à ce qu'une entité de sécurité est attachée à chaque thread. L'entité de sécurité, en fonction de IPrincipal, encapsule l'identité de l'utilisateur authentifié dans une implémentation d'IIdentity. WIF fournit ClaimsPrincipal et ClaimsIdentity types basés sur IClaimsPrincipal et IClaimsIdentity (qui, au final, dérivent à partir de IPrincipal et IIdentity). Lorsque le FAM traite la réponse de connexion, il hydrates un ClaimsPrincipal pour le jeton de sécurité émis. De même, le Gestionnaire SAM hydrates un ClaimsPrincipal pour le cookie de session. Cette ClaimsPrincipal est au cœur de l'autorisation WIF de votre application ASP.NET.

Vous pouvez utiliser une des approches suivantes à l'autorisation :

  • Utiliser les paramètres d'autorisation spécifiques à l'emplacement pour restreindre l'accès aux annuaires ou les ressources d'application individuels.
  • Utilisez les contrôles d'ouverture de session ASP.NET, tels que le contrôle LoginView, pour contrôler l'accès à la fonctionnalité.
  • Utilisez ClaimsPrincipal pour effectuer des vérifications d'IsInRole dynamiques (par exemple, pour masquer ou afficher les éléments d'interface utilisateur dynamique).
  • Utilisez le type de PrincipalPermission pour effectuer des demandes d'autorisation dynamique ou l'attribut PrincipalPermissionAttribute si la demande d'autorisation déclarative semble appropriée sur une méthode particulière.
  • Fournir un ClaimsAuthorizationManager personnalisé pour centraliser l'accès aux contrôles dans un seul composant, même avant de charger la ressource demandée.

Les trois premières de ces options s'appuient sur la méthode IsInRole exposée par le type ClaimsPrincipal. Vous devez sélectionner un rôle demande type ajustement pour le contrôle d'IsInRole pour que les revendications correctes seront utilisées pour contrôler l'accès. Le type de déclaration de rôle par défaut pour WIF est la suivante :

https://schemas.microsoft.com/ws/2008/06/identity/claims/role

Si ClaimsPrincipal inclut des déclarations définies, le type de déclaration de rôle associe la valeur par défaut. Plus tard, je traiterai des demandes d'autorisation dans le contexte de la transformation de déclarations. Lorsque ceux-ci sont utilisés, vous devez spécifier le type de demande d'autorisation en tant que le type de déclaration de rôle afin que IsInRole sera efficace.

Vous pouvez contrôler l'accès à des pages spécifiques ou des répertoires globalement dans le fichier web.config. Dans la racine d'application, fournissez une balise location qui spécifie le chemin d'accès à protéger, permettre à une liste de rôles acceptables et refuser l'accès à tous les autres utilisateurs. Seuls les administrateurs à accéder aux fichiers sous le répertoire AdminOnly permet des éléments suivants :

<location path="AdminOnly">
  <system.web>
    <authorization>
      <allow roles="Administrators" />
      <deny users="*"/>
    </authorization>
  </system.web>
</location>

Comme alternative, vous pouvez placer un fichier web.config dans n'importe quel sous-répertoire et spécifier des règles d'autorisation. Place la configuration suivante dans le répertoire et AdminOnly permet d'obtenir le même résultat :

<configuration>
  <system.web>
    <authorization >
      <allow roles="Administrators" />
      <deny users="*"/>
    </authorization>
  </system.web>
</configuration>

Pour masquer de façon dynamique et afficher les composants d'interface utilisateur ou contrôler l'accès aux fonctions dans une page, vous pouvez exploiter les fonctionnalités de base de rôles de contrôles, tels que le contrôle LoginView. Cependant, la plupart des développeurs préfèrent définir explicitement chargent les propriétés de contrôle d'accès lors de la page pour un contrôle plus granulaire de contrôle. Pour ce faire, vous pouvez appeler la méthode IsInRole exposée par les revendications du ­ principal. Vous pouvez accéder à l'objet principal actuel par le biais de la propriété statique de thread.CurrentPrincipal comme suit :

if (!Thread.CurrentPrincipal.IsInRole("Administrators"))
  throw new SecurityException("Access is denied.");

En-dehors des vérifications explicites de IsInRole lors de l'exécution, vous pouvez également écrire les demandes d'autorisation basée sur les rôles de classique à l'aide de l'objet principal ­ type de permission. Vous initialisez le type avec la revendication de rôle requise (le deuxième paramètre de constructeur) et, lorsque Demand est appelé, la méthode IsInRole du principal actuel est appelée. Une exception est levée si la revendication est introuvable :

PrincipalPermission p = 
  new PrincipalPermission("", "Administrators");
p.Demand();

Cette approche est utile pour refuser une demande avec une exception, lorsque les rôles appropriés ne sont pas présents.

Il est également utile centraliser les contrôles d'autorisation communs à toutes les ressources demandées. Dans certains cas, si vous disposez d'une stratégie de contrôle d'accès, par exemple, les règles stockées dans une base de données, vous pouvez utiliser un composant central de lire ces règles afin de contrôler l'accès aux fonctions et fonctionnalités. Pour ce faire, WIF fournit un composant ClaimsAuthorizationManager que vous pouvez étendre. Dans mon précédent article, rappelez-vous que vous pouvez configurer ce type de composant personnalisé dans la section de modèle d'identité :

<microsoft.identityModel>
  <service>
    <!--other settings-->
    <claimsAuthorizationManager 
      type="CustomClaimsAuthorizationManager"/>
  </service>
</microsoft.identityModel>

La figure 7 illustre un ClaimsAuthorizationManager personnalisée qui vérifie la présence de la déclaration de nom et si la ressource demandée se trouve dans le répertoire AdminsOnly nécessite la déclaration de rôle Administrateurs.

Figure 7 Implémentation de ClaimsAuthorizationManager personnalisé

public class CustomClaimsAuthorizationManager: 
  ClaimsAuthorizationManager {

  public CustomClaimsAuthorizationManager()
  { }

  public override bool CheckAccess(
    AuthorizationContext context) {

    ClaimsIdentity claimsIdentity = 
      context.Principal.Identity as ClaimsIdentity;
    if (claimsIdentity.Claims.Where(
      x => x.ClaimType == ClaimTypes.Name).Count() <= 0)
      throw new SecurityException("Access is denied.");
        
    IEnumerable<Claim> resourceClaims = 
      context.Resource.Where(x=>x.ClaimType==ClaimTypes.Name);
    if (resourceClaims.Count() > 0) {
      foreach (Claim c in resourceClaims) {
        if (c.Value.Contains("\AdminOnly") && 
          !context.Principal.IsInRole("Administrators"))
          throw new SecurityException("Access is denied.");
      }
    }

    return true;
  }
}

Le CustomClaimsAuthorizationManager substitue à cocher ­ Access pour fournir cette fonctionnalité. Cette méthode fournit un paramètre AuthorizationContext qui fournit des informations sur l'action de demande (pour la fédération passive c'est un verbe HTTP, tels que GET ou POST), la ressource demandée (URI) et le ­ de revendications principal, ce qui n'est pas encore attaché au thread de demande.

Transformation de déclarations

Souvent, les affirmations émises par le SJS IP, bien qu'utiles pour la description de l'utilisateur authentifié, ne sont pas pertinentes pour les exigences d'autorisation du RP. Il n'est pas travail du IdP pour savoir quel type de rôles, les autorisations ou les autres artefacts granularité fine est nécessaire pour l'autorisation à chaque RP. Travail du IdP consiste à accorder les demandes qui conviennent au domaine de fournisseur d'identité, les déclarations qui peut faire en sorte le IdP à propos de l'utilisateur authentifié.

Par conséquent, le RP peut est nécessaire transformer les demandes à partir de l'IP/STS en quelque chose de plus pertinents pour l'autorisation. Ceci implique que le RP peut mapper l'identité d'utilisateur (par exemple en nom d'utilisateur ou l'UPN) pour une série de déclarations RP. En supposant que les revendications de rôle par défaut d'un subventions IP STS, figure 8 listes est un ensemble d'autorisations possible se plaint que le RP pourrait émettre basé sur chaque demande entrante de rôle. Le type de demande d'autorisation peut être un type de déclaration personnalisée défini par le RP, telles que :

urn:ClaimsAwareWebSite/2010/01/claims/permission

Il est recommandé de transformer des déclarations de SharePoint Team Services de IP entrantes avec un ClaimsAuthenticationManager personnalisé. Vous pouvez installer un ClaimsAuthenticationManager personnalisé en ajoutant le code suivant à la section microsoft.identityModel :

<microsoft.identityModel>
  <service>
    <!--other settings-->
    <claimsAuthenticationManager 
      type="CustomClaimsAuthenticationManager"/>
  </service>
</microsoft.identityModel>

La figure 9 présente un exemple CustomClaimsAuthenticationManager transforme entrant rôle demandes accordées par l'IP/STS en demandes d'autorisation pertinentes au RP.

La figure 8 Transforming rôle sinistres à des demandes d'autorisation au RP

Rôle de revendication Demandes d'autorisation
Administrateurs Créer, lire, mettre à jour, supprimer
Utilisateurs Créer, lire, mettre à jour
Invité Lecture

La figure 9 Custom Transformation de déclarations au RP

public class CustomClaimsAuthenticationManager: 
  ClaimsAuthenticationManager {

  public CustomClaimsAuthenticationManager() { }

  public override IClaimsPrincipal Authenticate(
    string resourceName, IClaimsPrincipal incomingPrincipal) {

    IClaimsPrincipal cp = incomingPrincipal;
    ClaimsIdentityCollection claimsIds = 
      new ClaimsIdentityCollection();

    if (incomingPrincipal != null && 
      incomingPrincipal.Identity.IsAuthenticated == true) {

      ClaimsIdentity newClaimsId = new ClaimsIdentity(
        "CustomClaimsAuthenticationManager", ClaimTypes.Name, 
        "urn:ClaimsAwareWebSite/2010/01/claims/permission");

      ClaimsIdentity claimsId = 
        incomingPrincipal.Identity as ClaimsIdentity;
      foreach (Claim c in claimsId.Claims)
        newClaimsId.Claims.Add(new Claim(
          c.ClaimType, c.Value, c.ValueType, 
          "CustomClaimsAuthenticationManager", c.Issuer));

      if (incomingPrincipal.IsInRole("Administrators")) {
        newClaimsId.Claims.Add(new Claim(
          "urn:ClaimsAwareWebSite/2010/01/claims/permission", 
          "Create"));
        newClaimsId.Claims.Add(new Claim(
          "urn:ClaimsAwareWebSite/2010/01/claims/permission", 
          "Read"));
        newClaimsId.Claims.Add(new Claim(
          "urn:ClaimsAwareWebSite/2010/01/claims/permission", 
          "Update"));
        newClaimsId.Claims.Add(new Claim(
          "urn:ClaimsAwareWebSite/2010/01/claims/permission", 
          "Delete"));
      }

      else if (incomingPrincipal.IsInRole("Users")) {
        newClaimsId.Claims.Add(new Claim(
          "urn:ClaimsAwareWebSite/2010/01/claims/permission", 
          "Create"));
        newClaimsId.Claims.Add(new Claim(
          "urn:ClaimsAwareWebSite/2010/01/claims/permission", 
          "Read"));
        newClaimsId.Claims.Add(new Claim(
          "urn:ClaimsAwareWebSite/2010/01/claims/permission", 
          "Update"));
      }

      else {
        newClaimsId.Claims.Add(new Claim(
          "urn:ClaimsAwareWebSite/2010/01/claims/permission", 
          "Read"));
      }

      claimsIds.Add(newClaimsId);
      cp = new ClaimsPrincipal(claimsIds);
    }

    return cp;
  }
}

Pour les contrôles d'IsInRole (comme décrit précédemment) pour fonctionner, vous devez fournir le type de demande d'autorisation comme le rôle de demander le type. Dans les figure 9-, elle est spécifiée lors de la ClaimsIdentity construction parce que le RP crée le ClaimsIdentity.

Dans le cas où les jetons SAML entrants sont la source de déclarations, vous pouvez fournir le type de demandes de rôle pour le SecurityTokenHandler. L'exemple suivant illustre comment faire pour configurer de manière déclarative Saml11SecurityTokenHandler pour utiliser le type de demande d'autorisations que le rôle de demander le type :

<microsoft.identityModel>
  <service>
    <!--other settings-->
    <securityTokenHandlers>
      <remove type="Microsoft.IdentityModel.Tokens.Saml11.Saml11SecurityTokenHandler, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add type="Microsoft.IdentityModel.Tokens.Saml11.Saml11SecurityTokenHandler, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
        <samlSecurityTokenRequirement >
          <roleClaimType 
            value= "urn:ClaimsAwareWebSite/2010/01/claims/permission"/>
        </samlSecurityTokenRequirement>
      </add>
    </securityTokenHandlers>
  </service>
</microsoft.identityModel>

Gestionnaires de jetons SAML ont une section samlSecurityTokenRequirement où vous pouvez fournir un paramètre pour le nom et le rôle dossiers type, ainsi que des autres paramètres liés à la validation des certificats et des jetons de Windows.

Découverte de domaine personnel

À ce stade, je me suis concentré sur un scénario simple de la fédération avec un STS de IP unique. Il est supposé que le RP redirigera toujours vers un STS d'IP spécifique pour authentifier les utilisateurs.

Toutefois, dans le monde de la fédération étendue, le RP peut approuver plusieurs émetteurs de jetons à partir de plusieurs domaines. Un nouveau défi affiche lui-même dans ce cas parce que le RP doit décider lequel SharePoint Team Services de IP doivent authentifier les utilisateurs demandant accès aux ressources. Le domaine auquel les utilisateurs s'authentifient est connu comme domaine de base de l'utilisateur, et donc ce processus est appelé découverte de domaine d'origine.

Il existe un certain nombre de mécanismes de qu'une application peut utiliser pour rechercher le domaine d'origine :

  • Comme dans l'exemple actuel, le domaine d'origine est connu dans avancées et c'est le cas des demandes sont toujours redirigés vers un STS de IP particulière.
  • Les utilisateurs peuvent naviguer vers le RP à partir d'un autre portail, ce qui peut fournir une chaîne de requête pour indiquer le domaine d'origine pour les utilisateurs à partir de ce portail.
  • Le RP peut nécessiter ces terres utilisateurs sur une page d'entrée particulière pour chaque domaine d'origine. La page de destination pourrait assumer un domaine particulier de base.
  • Le RP peut être en mesure de déterminer le domaine associé à l'adresse IP de la demande ou certains autre heuristique.
  • Si le RP ne peut pas déterminer le domaine d'origine à partir d'une des techniques susmentionnées, il peut présenter une interface utilisateur où l'utilisateur peut sélectionner le domaine d'origine ou fournir des informations qui vous aide au RP de le déterminer.
  • Si le RP prend en charge les cartes d'informations, la carte sélectionnée peut piloter d'authentification au domaine de base appropriées à l'aide de la fédération étendue active.
  • Le WS-Federation décrit brièvement la façon dont une peut implémenter un service de découverte pour la résolution du domaine d'origine, mais il n'est pas une spécification bien définie pour que cela.

Quel que soit la façon dont le domaine d'origine est découvert, l'objectif est de rediriger l'utilisateur pour s'authentifier avec le SJS de IP correct. Il n'y a quelques scénarios possibles. Dans l'un des scénarios, le RP peut est nécessaire définir dynamiquement l'URI de l'émetteur afin que la demande de connexion est envoyée vers le SJS de IP correct. Dans ce cas, le RP doit répertorier tous les IP-STS approuvés dans la section trustedIssuers, par exemple :

<trustedIssuers>
  <add thumbprint="6b887123330ae8d26c3e2ea3bb7a489fd609a076" 
    name="IP1" />
  <add thumbprint="d5bf17e2bf84cf2b35a86ea967ebab838d3d0747" 
    name="IP2" />
</trustedIssuers>

En outre, vous pouvez substituer l'événement RedirectingToIdentityProvider exposée par la FAM et à l'aide d'analyse heuristique pertinents, déterminer l'URI pour les SharePoint Team Services. Pour ce faire, placez le code suivant dans l'implémentation de global.asax :

void WSFederationAuthenticationModule_RedirectingToIdentityProvider(
  object sender, RedirectingToIdentityProviderEventArgs e) {
  if (e.SignInRequestMessage.RequestUrl.Contains(
    "IP1RealmEntry.aspx")) {
    e.SignInRequestMessage.BaseUri = 
      new Uri("https://localhost/IP1/STS/Default.aspx");
  }
  else if (e.SignInRequestMessage.RequestUrl.Contains(
    "IP2RealmEntry.aspx")) {
    e.SignInRequestMessage.BaseUri = new Uri(
       "https://localhost/IP2/STS/Default.aspx");
  }
}

L'autre scénario implique en passant le paramètre domaine d'origine (whr) avec la demande de connexion vers le SJS principal. Le RP peut, par exemple, avoir une ressource STS (R-SharePoint Team Services ou SharePoint Team Services de RP) responsable de la transformation de déclarations. Le SJS de RP n'est pas authentifier les utilisateurs (ce n'est pas un IdP), mais elle a des relations d'approbation avec un ou plusieurs autres IdPs.

Le RP a une relation d'approbation avec le SJS de RP et respecte toujours les jetons émis par le SJS de RP. Les RP-SharePoint Team Services est responsable de la redirection vers le IdP correct pour chaque demande. Le SJS de RP peut déterminer le SJS de IP correct pour rediriger vers, comme dans le code décrit précédemment, mais une autre option consiste pour le RP fournir des informations sur le domaine d'origine, ceci en passant dans le paramètre domaine d'origine vers le SJS de RP. Dans ce cas, le RP définit dynamiquement le paramètre domaine d'origine :

void WSFederationAuthenticationModule_RedirectingToIdentityProvider(
  object sender, RedirectingToIdentityProviderEventArgs e) {
  if (e.SignInRequestMessage.RequestUrl.Contains(
    "IP1RealmEntry.aspx")) {
    e.SignInRequestMessage.HomeRealm = 
      "https://localhost/IP1/STS/Default.aspx";
  }
  else if (e.SignInRequestMessage.RequestUrl.Contains(
    "IP2RealmEntry.aspx")) {
    e.SignInRequestMessage.HomeRealm = 
      "https://localhost/IP2/STS/Default.aspx";
  }
}

Le SJS de RP utilise ce paramètre pour rediriger vers le SJS de IP correct et transforme par la suite des déclarations à partir de l'IP/STS en demandes appropriées vers le RP.

Simple Sign-on et Single déconnexion

L'ouverture de session unique et simple déconnexion constituent un aspect important de la fédération. L'ouverture de session unique est une fonctionnalité qui autorise les utilisateurs authentifiés à accéder à plusieurs applications RP lors de l'authentification qu'une seule fois. Seul déconnexion, comme l'indique, il facilite la déconnexion de toutes les applications du RP et toute chaîne de SharePoint Team Services pertinent avec une seule demande.

Dans une fédération simple scénario comme celui présenté dans de la figure 1 , l'utilisateur s'authentifie l'IP/STS et est autorisé au RP basé sur le jeton de sécurité émis. POST-Authentication, l'utilisateur a un cookie de session pour les SharePoint Team Services et l'autre pour le RP. Maintenant, si l'utilisateur accède à un autre RP, elle va être redirigée vers le SJS de IP pour l'authentification, en supposant que les deux applications RP approuver le SJS de IP même. Parce que l'utilisateur a déjà ouvert une session avec l'IP/STS, le SJS émet un jeton pour le deuxième RP sans vous demander vos informations d'identification. Maintenant, l'utilisateur a accès à la deuxième RP et dispose d'un cookie de la nouvelle session pour le deuxième RP.

Comme je l'ai mentionné, WIF fournit le SAM pour écrire le cookie de session pour les utilisateurs authentifiés. Par défaut, ce cookie de session est émis pour l'adresse de l'application relatif pour le domaine et son nom de base est FedAuth. Les cookies de session fédéré peuvent être volumineux, le jeton est généralement divisé en les cookies de deux (ou plus) : FedAuth, FedAuth1 et ainsi de suite.

Si vous hébergez plusieurs applications au niveau du même domaine, dans le cadre du scénario de fédération étendue, le comportement par défaut est que le navigateur a un cookie FedAuth pour chaque RP (voir la rubrique figure 10 ). Le navigateur envoie uniquement ces cookies associés avec le domaine et le chemin d'accès pour la demande.

image: Session Cookies Associated with Each RP and the STS

La figure 10 de cookies de session associé à chaque RP et le SJS

Ce comportement par défaut est généralement correcte, mais il est parfois nécessaire de fournir un nom unique pour chaque cookie de session par l'application, en particulier s'ils sont hébergés sur le même domaine. Ou plusieurs applications au niveau du même domaine peuvent partager un cookie de session, auquel cas vous pouvez définir le chemin d'accès du cookie “ / ”.

Si le cookie de session expire, le navigateur le supprime à partir du cache et l'utilisateur est redirigé une fois de plus vers le SJS pour l'authentification. Séparément, si le jeton associé avec le cookie de session a expiré, WIF redirigera vers le SJS pour un nouveau jeton.

Déconnexion est plus explicite, en général piloté par l'utilisateur. Seul déconnexion est une fonctionnalité facultative de la spécification WS-Federation qui propose le SJS doit aussi notifier d'autres applications de RP pour lequel il a délivré des jetons de la demande de déconnexion. De cette manière, le cookie de session est supprimé de toutes les applications parcourir l'utilisateur sélectionné lors de la session d'ouverture de session unique. Dans un scénario plus complexe, où plusieurs STSs sont impliqués, le SJS principal reçoit la demande de déconnexion doit aussi notifier d'autres STSs pour effectuer la même opération.

Vue de cette discussion, je me concentrerai sur ce que doit faire au RP pour faciliter la fédéré unique de déconnexion. Vous pouvez placer le contrôle FederatedPassiveSignInStatus sur n'importe quelle page à partir de laquelle vous souhaitez prendre en charge connexion et déconnexion et le contrôle indique automatiquement son état. Une fois signé complémentaire, le contrôle présente un lien, le bouton ou l'image pour la déconnexion.

Lorsque vous cliquez sur le contrôle, elle gérera déconnexion en fonction de la propriété SignOutAction, ce qui peut être actualiser, redirection, RedirectToLoginPage ou FederatedPassiveSignOut. Les trois premières supprime le cookie de session pour l'application, mais ne pas avertir le SJS de la demande de déconnexion. Lorsque vous sélectionnez le paramètre FederatedPassiveSignOut, le contrôle appelle SignOut sur WSFederationAuthenticationModule. Cela garantit que les cookies de session fédérées sont supprimés de l'application. En outre, une demande de déconnexion est envoyée vers le SJS :

GET https://localhost/IP1/STS?wa=wsignout1.0

Si vous n'utilisez pas le contrôle FederatedPassiveSignInStatus, vous pouvez appeler directement WSFederationAuthenticationModule.SignOut pour déclencher une redirection vers le SJS avec la demande de déconnexion.

L'unique déconnexion indique que l'utilisateur est déconnecté de toutes les applications, qu'il est connectée à avec son identité fédérée. Si le SJS prend en charge cela, il doit contenir une liste d'applications de RP l'utilisateur connecté durant sa session et de sortie une demande de nettoyage pour chaque RP lorsque fédéré de déconnexion est demandée à :

GET https://localhost/ClaimsAwareWebSite?wa=wsignoutcleanup1.0

Dans des scénarios plus complexes, la même demande de nettoyage doit être envoyée à n'importe quel autres SharePoint Team Services impliquée dans la session fédérée.Pour cela, le SJS aurait d'avoir une connaissance préalable de l'URI de nettoyage pour chaque RP et un STS.Pour prendre en charge unique déconnexion, le RP doit être en mesure de traiter ces requêtes de nettoyage.Le FAM et le contrôle FederatedPassiveSignInStatus prend en charge cela.Si vous utilisez le FAM, la demande de nettoyage peut être publiée sur n'importe quel URI dans le RP et le FAM traitera la demande et nettoyer tous les cookies de session.Si vous utilisez le contrôle FederatedPassiveSignInStatus, la demande de nettoyage doit être publiée à une page qui contient le contrôle.

En fait, la spécification WS-Federation ne détaille pas comment faire pour implémenter le comportement de déconnexion et de nettoyage simple au-delà des chaînes de requête recommandées et des flux de communication.Il n'est pas facile de garantir unique déconnexion sera effective sur tous les partenaires de fédération étendue en conséquence, mais si vous possédez l'environnement et les choix pour atteindre cet objectif, il est en effet possible.

Michele Leroux Bustamante est le principal architecte à IDesign (idesign.net) et l'architecte responsable de la sécurité au niveau de BiTKOO ( bitkoo.com de ). Elle est également un directeur régional Microsoft pour San Diego et MVP Microsoft pour les systèmes connectés. Consultez son blog à dasblonde.netde .

Grâce à l'expert technique suivante pour la révision de cet article : Govind Ramanathan