Federazione

In questo argomento viene illustrato brevemente il concetto di sicurezza federata. Descrive inoltre il supporto di Windows Communication Foundation (WCF) per la distribuzione di architetture di sicurezza federate. Per un'applicazione di esempio sulla federazione, vedere Esempio di federazione.

Definizione di sicurezza federata

La protezione federata consente di separare con precisione il servizio al quale sta accedendo un client dalle procedure pertinenti di autenticazione e di autorizzazione. La protezione federata consente inoltre la collaborazione attraverso più sistemi, reti e organizzazioni in diverse aree di attendibilità.

WCF fornisce il supporto per creare e distribuire sistemi distribuiti che utilizzano la protezione federata.

Elementi di un'architettura di sicurezza federata

L'architettura di sicurezza federata è composta da tre elementi principali, come descritto nella tabella seguente.

Elemento Descrizione
Dominio/area Una singola unità di amministrazione di sicurezza o attendibilità. Un dominio tipico potrebbe includere una sola organizzazione.
Federazione Una raccolta di domini che hanno stabilito una relazione di trust. Il livello di attendibilità può variare, ma in genere include l'autenticazione e quasi sempre l'autorizzazione. Una federazione tipica può includere numerose organizzazioni che hanno stabilito una relazione di trust per l'accesso condiviso per un set di risorse.
Servizio Token di sicurezza (STS, Security Token Service) Servizio Web che rilascia token di sicurezza, ovvero, fa asserzioni basate su evidenze che considera attendibili, a chiunque lo consideri attendibile. Questa è la base della negoziazione di attendibilità tra domini.

Scenario di esempio

Nella figura seguente viene illustrato un esempio di sicurezza federata:

Diagram showing a typical federated security scenario.

In questo scenario sono incluse due organizzazioni: A e B. L'organizzazione B ha una risorsa Web (un servizio Web) che alcuni utenti dell'organizzazione A ritengono preziosa.

Nota

Contenuto della sezione, vengono utilizzati indifferentemente i termini risorsa, servizio e servizio Web.

L'organizzazione B richiede in genere che un utente dell'organizzazione A fornisca un tipo valido di autenticazione prima di accedere al servizio. Potrebbe inoltre richiedere che l'utente venga autorizzato ad accedere alla risorsa specifica in questione. Un modo per risolvere questo problema e consentire agli utenti dell'organizzazione A di accedere alla risorsa nell'organizzazione B è il seguente:

  • Gli utenti dell'organizzazione A registrano le proprie credenziali (un nome utente e una password) presso l'organizzazione B.

  • Durante l'accesso alla risorsa, gli utenti dell'organizzazione A presentano le proprie credenziali all'organizzazione B e vengono autenticati prima di accedere alla risorsa.

Questo approccio ha tre grandi inconvenienti:

  • L'organizzazione B deve gestire le credenziali degli utenti dell'organizzazione A, oltre a quelle dei propri utenti locali.

  • Gli utenti dell'organizzazione A devono mantenere un set aggiuntivo di credenziali (ovvero, ricordare un nome utente e una password in più), oltre a quelle normalmente utilizzate per accedere alle risorse all'interno dell'organizzazione A. Ciò incoraggia la pratica dell'utilizzo dello stesso nome utente e della stessa password in più siti del servizio, il che non è una misura efficace di sicurezza.

  • L'architettura non si adatta, in quanto più organizzazioni percepiscono la risorsa dell'organizzazione B come di un qualche valore.

Un approccio alternativo, che risolve gli inconvenienti menzionati in precedenza, consiste nell'utilizzare la protezione federata. In questo approccio, le organizzazioni A e B stabiliscono una relazione di trust e utilizzano il servizio token di sicurezza (STS, Security Token Service) per consentire la negoziazione della relazione di trust stabilita.

In un'architettura di sicurezza federata, gli utenti dell'organizzazione A sanno che se vogliono accedere al servizio Web dell'organizzazione B devono presentare un token di sicurezza valido dall'STS dell'organizzazione B, che autentica e autorizza il loro accesso al servizio specifico.

Quando contattano l'STS B, gli utenti ricevono un altro livello di riferimento indiretto dal criterio associato a STS. Devono presentare un token di sicurezza valido da STS A (ovvero, l'area di attendibilità del client) prima che STS B possa rilasciare loro un token di sicurezza. Si tratta di un corollario della relazione di trust stabilita tra le due organizzazioni e implica che l'organizzazione B non deve gestire le identità degli utenti dell'organizzazione A. In pratica, STS B in genere ha issuerAddress e issuerMetadataAddress nulli. Per altre informazioni, vedere Procedura: Configurare un'autorità di certificazione locale. In quel caso, il client consulta un criterio locale per individuare STS A. Questa configurazione è chiamata federazione dell'area di autenticazione principale e si adatta meglio perché STS B non deve conservare informazioni su STS A.

Gli utenti contattano quindi l'STS dell'organizzazione A e ottengono un token di sicurezza presentando le credenziali di autenticazione che utilizzano normalmente per accedere a qualsiasi altra risorsa all'interno dell'organizzazione A. In tal modo, si evita loro di dover conservare più set di credenziali o utilizzare lo stesso set di credenziali in più siti del servizio.

Una volta ottenuto un token di sicurezza da STS A, gli utenti lo presentano a STS B. L'organizzazione B procede per eseguire l'autorizzazione delle richieste degli utenti e rilascia loro un token di sicurezza preso dal proprio set di token di sicurezza. Gli utenti possono presentare quindi il proprio token alla risorsa dell'organizzazione B e accedere al servizio.

Supporto per la protezione federata in WCF

WCF fornisce un supporto chiavi in mano per la distribuzione di architetture di sicurezza federata tramite <wsFederationHttpBinding>.

L'elemento <wsFederationHttpBinding> offre un'associazione sicura, affidabile e interoperativa che comporta l'utilizzo di HTTP come meccanismo di trasporto sottostante per lo stile di comunicazione request/reply, utilizzando testo e XML come formato wire per la codifica.

L'utilizzo di <wsFederationHttpBinding> in uno scenario di sicurezza federata può essere separato in due fasi logicamente indipendenti, come descritto nelle sezioni seguenti.

Fase 1: Progettazione

Durante la fase di progettazione, il client utilizza lo strumento ServiceModel Metadata Utility Tool (Svcutil.exe) per leggere il criterio esposto dall'endpoint del servizio e raccogliere i requisiti di autenticazione e autorizzazione del servizio. Vengono costruiti proxy adatti per creare il modello di comunicazione di sicurezza federata seguente nel client:

  • Ottenere un token di sicurezza da STS nell'area di attendibilità del client.

  • Presentare il token a STS nell'area di attendibilità del servizio.

  • Ottenere un token di sicurezza da STS nell'area di attendibilità del servizio.

  • Presentare il token al servizio per accedere ad esso.

Fase 2: Runtime

Durante la fase runtime, il client crea un'istanza di un oggetto della classe client WCF e fa una chiamata utilizzando il client WCF. Il framework sottostante di WCF gestisce i passaggi menzionati in precedenza nel modello di comunicazione di sicurezza federata e consente al client di usare facilmente il servizio.

Implementazione di esempio utilizzando WCF

Nella figura seguente viene illustrata un'implementazione di esempio per un'architettura di sicurezza federata utilizzando il supporto nativo da WCF.

Diagram showing a sample Federation security implementation.

Esempio MyService

Il servizio MyService espone un singolo endpoint tramite MyServiceEndpoint. Nella figura seguente vengono illustrati l'indirizzo, l'associazione e il contratto associati all'endpoint.

Diagram showing the MyServiceEndpoint details.

L'endpoint del servizio MyServiceEndpoint utilizza <wsFederationHttpBinding> e richiede un token Security Assertions Markup Language (SAML) valido con un'attestazione accessAuthorized rilasciata da STS B. Questo è specificato in modo dichiarativo nella configurazione del servizio.

<system.serviceModel>  
  <services>  
    <service type="FederationSample.MyService"
        behaviorConfiguration='MyServiceBehavior'>  
        <endpoint address=""  
            binding=" wsFederationHttpBinding"  
            bindingConfiguration='MyServiceBinding'  
            contract="Federation.IMyService" />  
   </service>  
  </services>  
  
  <bindings>  
    <wsFederationHttpBinding>  
    <!-- This is the binding used by MyService. It redirects   
    clients to STS-B. -->  
      <binding name='MyServiceBinding'>  
        <security mode="Message">  
           <message issuedTokenType=  
"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">  
           <issuer address="http://localhost/FederationSample/STS-B/STS.svc" />  
            <issuerMetadata
           address=  
"http://localhost/FederationSample/STS-B/STS.svc/mex" />  
         <requiredClaimTypes>  
            <add claimType="http://tempuri.org:accessAuthorized" />  
         </requiredClaimTypes>  
        </message>  
      </security>  
      </binding>  
    </wsFederationHttpBinding>  
  </bindings>  
  
  <behaviors>  
    <behavior name='MyServiceBehavior'>  
      <serviceAuthorization
operationRequirementType="FederationSample.MyServiceOperationRequirement, MyService" />  
       <serviceCredentials>  
         <serviceCertificate findValue="CN=FederationSample.com"  
         x509FindType="FindBySubjectDistinguishedName"  
         storeLocation='LocalMachine'  
         storeName='My' />  
      </serviceCredentials>  
    </behavior>  
  </behaviors>  
</system.serviceModel>  

Nota

In relazione alle attestazioni richieste da MyService, è opportuno tenere presente un fattore importante. La seconda figura indica che MyService richiede un token SAML con l'attestazione accessAuthorized. Per essere più precisi, viene specificato il tipo di attestazione richiesto da MyService. Il nome completo di questo tipo di attestazione è http://tempuri.org:accessAuthorized (insieme allo spazio dei nomi associato), utilizzato nel file di configurazione del servizio. Il valore di questa attestazione indica la sua presenza e si presuppone che sia impostato su true da STS B.

In fase di esecuzione, questo criterio viene imposto dalla classe MyServiceOperationRequirement implementata come parte di MyService.

using System.Collections.Generic;
using System.IdentityModel.Claims;
using System.IdentityModel.Policy;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
Imports System.Collections.Generic
Imports System.IdentityModel.Claims
Imports System.IdentityModel.Policy
Imports System.IdentityModel.Tokens
Imports System.Security.Cryptography.X509Certificates
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Security.Tokens
Imports System.Text
public class myServiceAuthorizationManager : ServiceAuthorizationManager
{
    // Override the CheckAccess method to enforce access control requirements.
    public override bool CheckAccess(OperationContext operationContext)
    {
        AuthorizationContext authContext =
        operationContext.ServiceSecurityContext.AuthorizationContext;
        if (authContext.ClaimSets == null) return false;
        if (authContext.ClaimSets.Count != 1) return false;
        ClaimSet myClaimSet = authContext.ClaimSets[0];
        if (!IssuedBySTS_B(myClaimSet)) return false;
        if (myClaimSet.Count != 1) return false;
        Claim myClaim = myClaimSet[0];
        if (myClaim.ClaimType ==
          "http://www.tmpuri.org:accessAuthorized")
        {
            string resource = myClaim.Resource as string;
            if (resource == null) return false;
            if (resource != "true") return false;
            return true;
        }
        else
        {
            return false;
        }
    }

    // This helper method checks whether SAML Token was issued by STS-B.
    // It compares the Thumbprint Claim of the Issuer against the
    // Certificate of STS-B.
    private bool IssuedBySTS_B(ClaimSet myClaimSet)
    {
        ClaimSet issuerClaimSet = myClaimSet.Issuer;
        if (issuerClaimSet == null) return false;
        if (issuerClaimSet.Count != 1) return false;
        Claim issuerClaim = issuerClaimSet[0];
        if (issuerClaim.ClaimType != ClaimTypes.Thumbprint)
            return false;
        if (issuerClaim.Resource == null) return false;
        byte[] claimThumbprint = (byte[])issuerClaim.Resource;
        // It is assumed that stsB_Certificate is a variable of type
        // X509Certificate2 that is initialized with the Certificate of
        // STS-B.
        X509Certificate2 stsB_Certificate = GetStsBCertificate();
        byte[] certThumbprint = stsB_Certificate.GetCertHash();
        if (claimThumbprint.Length != certThumbprint.Length)
            return false;
        for (int i = 0; i < claimThumbprint.Length; i++)
        {
            if (claimThumbprint[i] != certThumbprint[i]) return false;
        }
        return true;
    }
Public Class myServiceAuthorizationManager
    Inherits ServiceAuthorizationManager

    ' Override the CheckAccess method to enforce access control requirements.
    Public Overloads Overrides Function CheckAccess(ByVal operationContext As OperationContext) As Boolean
        Dim authContext = operationContext.ServiceSecurityContext.AuthorizationContext
        If authContext.ClaimSets Is Nothing Then
            Return False
        End If

        If authContext.ClaimSets.Count <> 1 Then
            Return False
        End If

        Dim myClaimSet = authContext.ClaimSets(0)
        If Not IssuedBySTS_B(myClaimSet) Then
            Return False
        End If
        If myClaimSet.Count <> 1 Then
            Return False
        End If
        Dim myClaim = myClaimSet(0)
        If myClaim.ClaimType = "http://www.tmpuri.org:accessAuthorized" Then
            Dim resource = TryCast(myClaim.Resource, String)
            If resource Is Nothing Then
                Return False
            End If
            If resource <> "true" Then
                Return False
            End If
            Return True
        Else
            Return False
        End If
    End Function

    ' This helper method checks whether SAML Token was issued by STS-B.     
    ' It compares the Thumbprint Claim of the Issuer against the 
    ' Certificate of STS-B. 
    Private Function IssuedBySTS_B(ByVal myClaimSet As ClaimSet) As Boolean
        Dim issuerClaimSet = myClaimSet.Issuer
        If issuerClaimSet Is Nothing Then
            Return False
        End If
        If issuerClaimSet.Count <> 1 Then
            Return False
        End If
        Dim issuerClaim = issuerClaimSet(0)
        If issuerClaim.ClaimType <> ClaimTypes.Thumbprint Then
            Return False
        End If
        If issuerClaim.Resource Is Nothing Then
            Return False
        End If
        Dim claimThumbprint() = CType(issuerClaim.Resource, Byte())
        ' It is assumed that stsB_Certificate is a variable of type 
        ' X509Certificate2 that is initialized with the Certificate of 
        ' STS-B.
        Dim stsB_Certificate = GetStsBCertificate()
        Dim certThumbprint() = stsB_Certificate.GetCertHash()
        If claimThumbprint.Length <> certThumbprint.Length Then
            Return False
        End If
        For i = 0 To claimThumbprint.Length - 1
            If claimThumbprint(i) <> certThumbprint(i) Then
                Return False
            End If
        Next i
        Return True
    End Function

STS B

Nella figura seguente viene illustrato STS B. Come dichiarato precedentemente, un servizio token di sicurezza (STS) è anche un servizio Web a cui possono essere associati endpoint, criterio e così via.

Diagram showing security token service B.

STS B espone un singolo endpoint, chiamato STSEndpoint che può essere utilizzato per richiedere token di sicurezza. Nello specifico, STS B rilascia token SAML con l'attestazione accessAuthorized, che può essere presentata al sito del servizio MyService per accedere al servizio. STS B richiede tuttavia che gli utenti presentino un token SAML valido rilasciato da STS A, contenente l'attestazione userAuthenticated. Questo è specificato in modo dichiarativo nella configurazione STS.

<system.serviceModel>  
  <services>  
    <service type="FederationSample.STS_B" behaviorConfiguration=  
     "STS-B_Behavior">  
    <endpoint address=""  
              binding="wsFederationHttpBinding"  
              bindingConfiguration='STS-B_Binding'  
      contract="FederationSample.ISts" />  
    </service>  
  </services>  
  <bindings>  
    <wsFederationHttpBinding>  
    <!-- This is the binding used by STS-B. It redirects clients to   
         STS-A. -->  
      <binding name='STS-B_Binding'>  
        <security mode='Message'>  
          <message issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">  
          <issuer address='http://localhost/FederationSample/STS-A/STS.svc' />  
          <issuerMetadata address='http://localhost/FederationSample/STS-A/STS.svc/mex'/>  
          <requiredClaimTypes>  
            <add claimType='http://tempuri.org:userAuthenticated'/>  
          </requiredClaimTypes>  
          </message>  
        </security>  
    </binding>  
   </wsFederationHttpBinding>  
  </bindings>  
  <behaviors>  
  <behavior name='STS-B_Behavior'>  
    <serviceAuthorization   operationRequirementType='FederationSample.STS_B_OperationRequirement, STS_B' />  
    <serviceCredentials>  
      <serviceCertificate findValue='CN=FederationSample.com'  
      x509FindType='FindBySubjectDistinguishedName'  
       storeLocation='LocalMachine'  
       storeName='My' />  
     </serviceCredentials>  
   </behavior>  
  </behaviors>  
</system.serviceModel>  

Nota

Anche qui, l'attestazione userAuthenticated è il tipo di attestazione richiesto da STS B. Il nome completo di questo tipo di attestazione è http://tempuri.org:userAuthenticated (insieme allo spazio dei nomi associato), utilizzato nel file di configurazione STS. Il valore di questa attestazione indica la sua presenza e si presuppone che sia impostato su true da STS A.

In fase di esecuzione, questo criterio viene imposto dalla classe STS_B_OperationRequirement implementata come parte di STS B.

public class STS_B_AuthorizationManager : ServiceAuthorizationManager
{

    // Override AccessCheck to enforce access control requirements.
    public override bool CheckAccess(OperationContext operationContext)
    {
        AuthorizationContext authContext =
        operationContext.ServiceSecurityContext.AuthorizationContext;
        if (authContext.ClaimSets == null) return false;
        if (authContext.ClaimSets.Count != 1) return false;
        ClaimSet myClaimSet = authContext.ClaimSets[0];
        if (!IssuedBySTS_A(myClaimSet)) return false;
        if (myClaimSet.Count != 1) return false;
        Claim myClaim = myClaimSet[0];
        if (myClaim.ClaimType == "http://www.tmpuri.org:userAuthenticated")
        {
            string resource = myClaim.Resource as string;
            if (resource == null) return false;
            if (resource != "true") return false;
            return true;
        }
        else
        {
            return false;
        }
    }

    // This helper method checks whether SAML Token was issued by STS-A.
    // It compares the Thumbprint Claim of the Issuer against the
    // Certificate of STS-A.
    private bool IssuedBySTS_A(ClaimSet myClaimSet)
    {
        ClaimSet issuerClaimSet = myClaimSet.Issuer;
        if (issuerClaimSet == null) return false;
        if (issuerClaimSet.Count != 1) return false;
        Claim issuerClaim = issuerClaimSet[0];
        if (issuerClaim.ClaimType != ClaimTypes.Thumbprint) return false;
        if (issuerClaim.Resource == null) return false;
        byte[] claimThumbprint = (byte[])issuerClaim.Resource;
        // It is assumed that stsA_Certificate is a variable of type X509Certificate2
        // that is initialized with the Certificate of STS-A.
        X509Certificate2 stsA_Certificate = GetStsACertificate();

        byte[] certThumbprint = stsA_Certificate.GetCertHash();
        if (claimThumbprint.Length != certThumbprint.Length) return false;
        for (int i = 0; i < claimThumbprint.Length; i++)
        {
            if (claimThumbprint[i] != certThumbprint[i]) return false;
        }
        return true;
    }
Public Class STS_B_AuthorizationManager
    Inherits ServiceAuthorizationManager

    ' Override AccessCheck to enforce access control requirements.
    Public Overloads Overrides Function CheckAccess(ByVal operationContext As OperationContext) As Boolean
        Dim authContext = operationContext.ServiceSecurityContext.AuthorizationContext
        If authContext.ClaimSets Is Nothing Then
            Return False
        End If
        If authContext.ClaimSets.Count <> 1 Then
            Return False
        End If
        Dim myClaimSet = authContext.ClaimSets(0)
        If Not IssuedBySTS_A(myClaimSet) Then
            Return False
        End If
        If myClaimSet.Count <> 1 Then
            Return False
        End If
        Dim myClaim = myClaimSet(0)
        If myClaim.ClaimType = "http://www.tmpuri.org:userAuthenticated" Then
            Dim resource = TryCast(myClaim.Resource, String)
            If resource Is Nothing Then
                Return False
            End If
            If resource <> "true" Then
                Return False
            End If
            Return True
        Else
            Return False
        End If
    End Function

    ' This helper method checks whether SAML Token was issued by STS-A. 
    ' It compares the Thumbprint Claim of the Issuer against the 
    ' Certificate of STS-A.
    Private Function IssuedBySTS_A(ByVal myClaimSet As ClaimSet) As Boolean
        Dim issuerClaimSet = myClaimSet.Issuer
        If issuerClaimSet Is Nothing Then
            Return False
        End If
        If issuerClaimSet.Count <> 1 Then
            Return False
        End If
        Dim issuerClaim = issuerClaimSet(0)
        If issuerClaim.ClaimType <> ClaimTypes.Thumbprint Then
            Return False
        End If
        If issuerClaim.Resource Is Nothing Then
            Return False
        End If
        Dim claimThumbprint() = CType(issuerClaim.Resource, Byte())
        ' It is assumed that stsA_Certificate is a variable of type X509Certificate2
        ' that is initialized with the Certificate of STS-A.
        Dim stsA_Certificate = GetStsACertificate()

        Dim certThumbprint() = stsA_Certificate.GetCertHash()
        If claimThumbprint.Length <> certThumbprint.Length Then
            Return False
        End If
        For i = 0 To claimThumbprint.Length - 1
            If claimThumbprint(i) <> certThumbprint(i) Then
                Return False
            End If
        Next i
        Return True
    End Function

Se il controllo di accesso è chiaro, STS B rilascia un token SAML con l'attestazione accessAuthorized.

// Create the list of SAML Attributes.
List<SamlAttribute> samlAttributes = new List<SamlAttribute>();

// Add the accessAuthorized claim.
List<string> strList = new List<string>();
strList.Add("true");
samlAttributes.Add(new SamlAttribute("http://www.tmpuri.org",
"accessAuthorized",
strList));

// Create the SAML token with the accessAuthorized claim. It is assumed that
// the method CreateSamlToken() is implemented as part of STS-B.
SamlSecurityToken samlToken = CreateSamlToken(
    proofToken,
    issuerToken,
    samlConditions,
    samlSubjectNameFormat,
    samlSubjectEmailAddress,
    samlAttributes);
' Create the list of SAML Attributes.
Dim samlAttributes As New List(Of SamlAttribute)()

' Add the accessAuthorized claim.
Dim strList As New List(Of String)()
strList.Add("true")
samlAttributes.Add(New SamlAttribute("http://www.tmpuri.org", "accessAuthorized", strList))

' Create the SAML token with the accessAuthorized claim. It is assumed that 
' the method CreateSamlToken() is implemented as part of STS-B.
Dim samlToken = CreateSamlToken(proofToken, _
                                issuerToken, _
                                samlConditions, _
                                samlSubjectNameFormat, _
                                samlSubjectEmailAddress, _
                                samlAttributes)

STS A

Nella figura seguente viene illustrato STS A.

Federation

Anche STS A, come STS B, è un servizio Web che rilascia token di sicurezza ed espone a tale fine un solo endpoint. Utilizza tuttavia un'associazione diversa (wsHttpBinding) e richiede che gli utenti presentino un CardSpace valido con un'attestazione emailAddress. In risposta, rilascia token SAML con l'attestazione userAuthenticated. Questo è specificato in modo dichiarativo nella configurazione del servizio.

<system.serviceModel>  
  <services>  
    <service type="FederationSample.STS_A" behaviorConfiguration="STS-A_Behavior">  
      <endpoint address=""  
                binding="wsHttpBinding"  
                bindingConfiguration="STS-A_Binding"  
                contract="FederationSample.ISts">  
       <identity>  
       <certificateReference findValue="CN=FederationSample.com"
                       x509FindType="FindBySubjectDistinguishedName"  
                       storeLocation="LocalMachine"
                       storeName="My" />  
       </identity>  
    </endpoint>  
  </service>  
</services>  
  
<bindings>  
  <wsHttpBinding>  
  <!-- This is the binding used by STS-A. It requires users to present  
   a CardSpace. -->  
    <binding name='STS-A_Binding'>  
      <security mode='Message'>  
        <message clientCredentialType="CardSpace" />  
      </security>  
    </binding>  
  </wsHttpBinding>  
</bindings>  
  
<behaviors>  
  <behavior name='STS-A_Behavior'>  
    <serviceAuthorization operationRequirementType=  
     "FederationSample.STS_A_OperationRequirement, STS_A" />  
      <serviceCredentials>  
  <serviceCertificate findValue="CN=FederationSample.com"  
                     x509FindType='FindBySubjectDistinguishedName'  
                     storeLocation='LocalMachine'  
                     storeName='My' />  
      </serviceCredentials>  
    </behavior>  
  </behaviors>  
</system.serviceModel>  

In fase di esecuzione, questo criterio viene imposto dalla classe STS_A_OperationRequirement implementata come parte di STS A.


public class STS_A_AuthorizationManager : ServiceAuthorizationManager
{
    // Override AccessCheck to enforce access control requirements.
    public override bool CheckAccess(OperationContext operationContext)
    {
        AuthorizationContext authContext =
        operationContext.ServiceSecurityContext.AuthorizationContext;
        if (authContext.ClaimSets == null) return false;
        if (authContext.ClaimSets.Count != 1) return false;
        ClaimSet myClaimSet = authContext.ClaimSets[0];
        if (myClaimSet.Count != 1) return false;
        Claim myClaim = myClaimSet[0];
        if ((myClaim.ClaimType ==
        @"http://schemas.microsoft.com/ws/2005/05/identity/claims:EmailAddress") &&
        (myClaim.Right == Rights.PossessProperty))
        {
            string emailAddress = myClaim.Resource as string;
            if (emailAddress == null) return false;
            if (!IsValidEmailAddress(emailAddress)) return false;
            return true;
        }
        else
        {
            return false;
        }
    }

    // This helper method performs a rudimentary check for whether
    //a given email is valid.
    private static bool IsValidEmailAddress(string emailAddress)
    {
        string[] splitEmail = emailAddress.Split('@');
        if (splitEmail.Length != 2) return false;
        if (!splitEmail[1].Contains(".")) return false;
        return true;
    }
}
Public Class STS_A_AuthorizationManager
    Inherits ServiceAuthorizationManager

    ' Override AccessCheck to enforce access control requirements.
    Public Overloads Overrides Function CheckAccess(ByVal operationContext As OperationContext) As Boolean
        Dim authContext = operationContext.ServiceSecurityContext.AuthorizationContext
        If authContext.ClaimSets Is Nothing Then
            Return False
        End If
        If authContext.ClaimSets.Count <> 1 Then
            Return False
        End If
        Dim myClaimSet = authContext.ClaimSets(0)
        If myClaimSet.Count <> 1 Then
            Return False
        End If
        Dim myClaim = myClaimSet(0)
        If myClaim.ClaimType = "http://schemas.microsoft.com/ws/2005/05/identity/claims:EmailAddress" AndAlso myClaim.Right = Rights.PossessProperty Then
            Dim emailAddress = TryCast(myClaim.Resource, String)
            If emailAddress Is Nothing Then
                Return False
            End If
            If Not IsValidEmailAddress(emailAddress) Then
                Return False
            End If
            Return True
        Else
            Return False
        End If
    End Function

    ' This helper method performs a rudimentary check for whether 
    'a given email is valid.
    Private Shared Function IsValidEmailAddress(ByVal emailAddress As String) As Boolean
        Dim splitEmail() = emailAddress.Split("@"c)
        If splitEmail.Length <> 2 Then
            Return False
        End If
        If Not splitEmail(1).Contains(".") Then
            Return False
        End If
        Return True
    End Function
End Class

Se l'accesso è true, STS A rilascia un token SAML con l'attestazione userAuthenticated.

// Create the list of SAML Attributes.
List<SamlAttribute> samlAttributes = new List<SamlAttribute>();
// Add the userAuthenticated claim.
List<string> strList = new List<string>();
strList.Add("true");
SamlAttribute mySamlAttribute = new SamlAttribute("http://www.tmpuri.org",
     "userAuthenticated", strList);
samlAttributes.Add(mySamlAttribute);
// Create the SAML token with the userAuthenticated claim. It is assumed that
// the method CreateSamlToken() is implemented as part of STS-A.
SamlSecurityToken samlToken = CreateSamlToken(
    proofToken,
    issuerToken,
    samlConditions,
    samlSubjectNameFormat,
    samlSubjectEmailAddress,
    samlAttributes);
' Create the list of SAML Attributes.
Dim samlAttributes As New List(Of SamlAttribute)()
' Add the userAuthenticated claim.
Dim strList As New List(Of String)()
strList.Add("true")
Dim mySamlAttribute As New SamlAttribute("http://www.tmpuri.org", _
                                         "userAuthenticated", _
                                         strList)
samlAttributes.Add(mySamlAttribute)
' Create the SAML token with the userAuthenticated claim. It is assumed that 
' the method CreateSamlToken() is implemented as part of STS-A.
Dim samlToken = CreateSamlToken(proofToken, issuerToken, samlConditions, _
                                samlSubjectNameFormat, _
                                samlSubjectEmailAddress, _
                                samlAttributes)

Client nell'organizzazione A

Nella figura seguente viene illustrato il client nell'organizzazione A, insieme ai passaggi necessari per eseguire una chiamata al servizio MyService. A fini di completezza, sono inclusi anche gli altri componenti funzionali.

Diagram showing the steps in a MyService service call.

Riepilogo

La protezione federata offre una divisione netta della responsabilità e contribuisce a creare architetture del servizio sicure e scalabili. Come piattaforma per la creazione e distribuzione di applicazioni distribuite, WCF fornisce supporto nativo per implementare la protezione federata.

Vedi anche