Federação

Este tópico fornece uma breve visão geral do conceito de segurança federada. Ele também descreve o suporte do WCF (Windows Communication Foundation) para a implantação de arquiteturas de segurança federada. Para obter um aplicativo de exemplo que demonstra a federação, consulte Exemplo de federação.

Definição da segurança federada

A segurança federada permite uma separação limpa entre o serviço que um cliente está acessando e os procedimentos de autenticação e autorização associados. A segurança federada também permite a colaboração em vários sistemas, redes e organizações em diferentes domínios de confiança.

O WCF dá suporte à criação e à implantação de sistemas distribuídos que empregam segurança federada.

Elementos de uma arquitetura de segurança federada

A arquitetura de segurança federada tem três elementos principais, conforme descrito na tabela a seguir.

Elemento Descrição
Domínio/realm Uma só unidade de administração ou confiança de segurança. Um domínio típico pode incluir uma só organização.
Federação Uma coleção de domínios que estabeleceram confiança. O nível de confiança pode variar, mas normalmente inclui a autenticação e quase sempre inclui a autorização. Uma federação típica pode incluir um número de organizações que estabeleceram confiança para acesso compartilhado a um conjunto de recursos.
STS (Serviço de Token de Segurança) Um serviço Web que emite tokens de segurança; ou seja, faz declarações baseadas em evidências de que confia, para quem confia nele. Isso forma a base da intermediação de confiança entre domínios.

Cenário de Exemplo

A seguinte ilustração mostra um exemplo de segurança federada:

Diagram showing a typical federated security scenario.

Esse cenário inclui duas organizações: A e B. A organização B tem um recurso da Web (um serviço Web) que alguns usuários na organização A acham valioso.

Observação

Esta seção usa os termos recurso, serviço e serviço Web de modo intercambiável.

Normalmente, a organização B exige que um usuário da organização A forneça alguma forma válida de autenticação antes de acessar o serviço. Além disso, a organização também pode exigir que o usuário esteja autorizado a acessar o recurso específico em questão. Uma maneira de resolver esse problema e permitir que os usuários na organização A acessem o recurso na organização B é a seguinte:

  • Os usuários da organização A registram suas credenciais (um nome de usuário e senha) com a organização B.

  • Durante o acesso aos recursos, os usuários da organização A apresentam suas credenciais para a organização B e são autenticados antes de acessar o recurso.

Essa abordagem tem três desvantagens significativas:

  • A organização B precisa gerenciar as credenciais dos usuários da organização A, além de gerenciar as credenciais de seus usuários locais.

  • Usuários na organização A precisam manter um conjunto adicional de credenciais (ou seja, lembrar de um nome de usuário e senha adicionais), além das credenciais que normalmente usam para obter acesso aos recursos dentro da organização A. Isso geralmente incentiva a prática de usar o mesmo nome de usuário e senha em vários sites de serviço, o que é uma medida de segurança fraca.

  • A arquitetura não é dimensionada à medida que mais organizações enxergam o recurso na organização B como sendo de algum valor.

Uma abordagem alternativa, que lida com as desvantagens mencionadas anteriormente, é empregar a segurança federada. Nessa abordagem, as organizações A e B estabelecem uma relação de confiança e empregam o STS (Serviço de Token de Segurança) para permitir a intermediação da confiança estabelecida.

Em uma arquitetura de segurança federada, os usuários da organização A sabem que, se quiserem acessar o serviço Web na organização B, deverão apresentar um token de segurança válido do STS na organização B, que autentica e autoriza seu acesso ao serviço específico.

Ao entrar em contato com o STS B, os usuários recebem outro nível de indireção da política associada ao STS. Eles devem apresentar um token de segurança válido do STS A (ou seja, o realm de confiança do cliente) antes que o STS B possa emitir um token de segurança. Esse é um corolário da relação de confiança estabelecida entre as duas organizações e implica que a organização B não precisa gerenciar identidades para usuários da organização A. Na prática, o STS B normalmente tem issuerAddress e issuerMetadataAddress nulos. Para obter mais informações, consulte Como configurar um emissor local. Nesse caso, o cliente consulta uma política local para localizar o STS A. Essa configuração é chamada de federação de realm inicial e é dimensionada melhor porque o STS B não precisa manter informações sobre o STS A.

Em seguida, os usuários entram em contato com o STS na organização A e obtêm um token de segurança apresentando credenciais de autenticação que normalmente usam para obter acesso a qualquer outro recurso dentro da organização A. Isso também alivia o problema de os usuários terem que manter vários conjuntos de credenciais ou usar o mesmo conjunto de credenciais em vários sites de serviço.

Depois que os usuários obtêm um token de segurança do STS A, eles apresentam o token para o STS B. A organização B prossegue para executar a autorização das solicitações dos usuários e emite um token de segurança para os usuários de seu conjunto de tokens de segurança. Em seguida, os usuários podem apresentar seu token ao recurso na organização B e acessar o serviço.

Suporte para segurança federada no WCF

O WCF dá suporte turnkey para implantar arquiteturas de segurança federadas por meio do <wsFederationHttpBinding>.

O elemento <wsFederationHttpBinding> fornece uma associação segura, confiável e interoperável que envolve o uso de HTTP como o mecanismo de transporte subjacente para o estilo de comunicação solicitação-resposta, empregando texto e XML como o formato de transmissão para codificação.

O uso de <wsFederationHttpBinding> em um cenário de segurança federado pode ser desacoplado em duas fases logicamente independentes, conforme descrito nas seções a seguir.

Fase 1: fase de design

Durante a fase de design, o cliente usa a Ferramenta de Utilitário de Metadados do ServiceModel (Svcutil.exe) para ler a política que o ponto de extremidade de serviço expõe e coletar os requisitos de autenticação e autorização do serviço. Os proxies apropriados são construídos para criar o seguinte padrão de comunicação de segurança federada no cliente:

  • Obter um token de segurança do STS no realm de confiança do cliente.

  • Apresentar o token ao STS no realm de confiança do serviço.

  • Obter um token de segurança do STS no realm de confiança do serviço.

  • Apresentar o token ao serviço para acessar o serviço.

Fase 2: fase de tempo de execução

Durante a fase de tempo de execução, o cliente cria uma instância de um objeto da classe de cliente WCF e faz uma chamada usando o cliente WCF. A estrutura subjacente do WCF lida com as etapas mencionadas anteriormente no padrão de comunicação de segurança federada e permite que o cliente consuma perfeitamente o serviço.

Implementação de exemplo usando o WCF

A ilustração a seguir mostra uma implementação de exemplo para uma arquitetura de segurança federada usando o suporte nativo do WCF.

Diagram showing a sample Federation security implementation.

Exemplo de MyService

O serviço MyService expõe um ponto de extremidade por meio de MyServiceEndpoint. A ilustração a seguir mostra o endereço, a associação e o contrato associados ao ponto de extremidade.

Diagram showing the MyServiceEndpoint details.

O ponto de extremidade de serviço MyServiceEndpoint usa <wsFederationHttpBinding> e requer um token SAML (Security Assertions Markup Language) válido com uma declaração accessAuthorized emitida pelo STS B. Isso é especificado declarativamente na configuração do serviço.

<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>  

Observação

Um detalhe deve ser observado sobre as declarações exigidas por MyService. A segunda figura indica que MyService requer um token SAML com a declaração accessAuthorized. Para ser mais preciso, isso especifica o tipo de declaração que MyService requer. O nome totalmente qualificado desse tipo de declaração é http://tempuri.org:accessAuthorized (juntamente com o namespace associado), que é usado no arquivo de configuração de serviço. O valor dessa declaração indica a presença dessa declaração e é considerado definido como true pelo STS B.

Em tempo de execução, essa política é imposta pela classe MyServiceOperationRequirement que é implementada como parte do 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

A ilustração a seguir mostra o STS B. Conforme mencionado anteriormente, um STS (serviço de token de segurança) também é um serviço Web e pode ter seus pontos de extremidade, política e assim por diante associados.

Diagram showing security token service B.

O STS B expõe um único ponto de extremidade, chamado STSEndpoint, que pode ser usado para solicitar tokens de segurança. Especificamente, o STS B emite tokens SAML com a declaração accessAuthorized, que pode ser apresentada no site de serviço MyService para acessar o serviço. No entanto, o STS B exige que os usuários apresentem um token SAML válido emitido pelo STS A que contém a declaração userAuthenticated. Isso é especificado declarativamente na configuração do 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>  

Observação

Novamente, a declaração userAuthenticated é o tipo de declaração exigido pelo STS B. O nome totalmente qualificado desse tipo de declaração é http://tempuri.org:userAuthenticated (juntamente com o namespace associado), que é usado no arquivo de configuração STS. O valor dessa declaração indica a presença dessa declaração e é considerado definido como true pelo STS A.

Em tempo de execução, a classe STS_B_OperationRequirement impõe essa política, que é implementada como parte do 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 a verificação de acesso estiver clara, o STS B emitirá um token SAML com a declaração 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

A ilustração a seguir mostra o STS A.

Federation

Semelhante ao STS B, o STS A também é um serviço Web que emite tokens de segurança e expõe um ponto de extremidade para essa finalidade. No entanto, ele usa uma associação diferente (wsHttpBinding) e exige que os usuários apresentem um CardSpace válido com uma declaração emailAddress. Em resposta, ele emite tokens SAML com a declaração userAuthenticated. Isso é especificado declarativamente na configuração do serviço.

<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>  

Em tempo de execução, a classe STS_A_OperationRequirement impõe essa política, que é implementada como parte do STS B.


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 o acesso for true, o STS A emitirá um token SAML com a declaração 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)

Cliente na organização A

A ilustração a seguir mostra o cliente na organização A, juntamente com as etapas envolvidas na realização de uma chamada de serviço MyService. Os outros componentes funcionais também são incluídos para integridade.

Diagram showing the steps in a MyService service call.

Resumo

A segurança federada fornece uma divisão limpa de responsabilidade e ajuda a criar arquiteturas de serviço seguras e escalonáveis. Como uma plataforma para criar e implantar aplicativos distribuídos, o WCF dá suporte nativo para implementar a segurança federada.

Confira também