Este artigo foi traduzido por máquina.

Identidade federada

Autenticação passiva para o ASP.NET com o WIF

Michele Leroux Leroux

O objetivo de segurança federada é fornecer um mecanismo para estabelecer relações de confiança entre domínios para que os usuários possam autenticar para o seu próprio domínio ao mesmo tempo em que está sendo concedido acesso aos aplicativos e serviços que pertencem a outro domínio. Isso possibilita que as técnicas de autenticação como o serviço single sign-on, elimina a necessidade de provisionar e gerenciar contas duplicadas para os usuários em domínios e de aplicativos e reduz significativamente o custo para estender os aplicativos de terceiros confiáveis.

Em um modelo de segurança federada, um provedor de identidade (IdP) executa a autenticação e fornece uma segurança token STS (serviço) para tokens de segurança do problema. Esses símbolos, por sua vez, informações sobre o usuário autenticado de declaração: sua identidade e possivelmente outras informações, incluindo as funções e direitos de acesso mais granulares. Em um mundo agrupado, essa informação é chamada de declarações e controle de acesso baseada em declarações é fundamental para um modelo de segurança federados. Nesse modelo, aplicativos e serviços de autorizam o acesso a recursos e funcionalidade com base em declarações de emissores confiáveis (STS).

Ferramentas de plataforma como o WIF (Windows Identity Foundation) facilitam muito o suporte a esse tipo de federação de identidades. WIF é uma estrutura de modelo de identidade para a criação de serviços e aplicativos baseados em declarações e para oferecer suporte baseado em SOAP (ativo) e cenários de federação de (passivo) baseado em navegador. No artigo “ autorização baseada em declarações com WIF , ” na edição de novembro de 2009, da MSDN Magazine, me concentrei em usando WIF com o Windows Communication Foundation (WCF). Nesse artigo, que descrevi como implementar modelos de segurança baseada em declarações para os serviços WCF e como migrar para a federação de identidades.

Este artigo de acompanhamento, me concentrarei na federação passiva. Irão explicar o fluxo de comunicação de federação passiva, mostrar a você várias técnicas para habilitar a federação nos aplicativos asp.net, discutir as técnicas de autorização baseada em declarações para o asp.net e falar sobre um único logon e único saídos cenários. Ao longo do processo, explicarei os recursos WIF subjacentes e componentes que oferecem suporte a cenários de federação passiva.

Noções básicas de federação passiva

Cenários de federação passiva baseiam-se na especificação WS-Federation. Descreve como solicitar tokens de segurança e como publicar e adquirir documentos de metadados de federação, que torna fácil a estabelecer relações de confiança. WS-Federation também descreve procedimentos de início de sessão e saída da rede único e outros conceitos de implementação de federação.

Enquanto o WS-Federation aborda muitos detalhes sobre a federação, há seções para a federação baseada em navegador que dependem do HTTP GET e POST, redirecionamentos de navegador e cookies para atingir a meta.

Alguns aspectos do serviço de federação passiva mensagens baseiam-se estritamente sobre a especificação WS-Trust. Por exemplo, a federação passiva emprega um formulário compatível com o navegador de token de segurança da solicitação (RST) e o RSTR (resposta de RST) quando um token de segurança é solicitado de um STS. O cenário de federação passiva, chamarei o RST uma mensagem de solicitação de início de sessão e a mensagem de resposta RSTR sign-in. A especificação WS-Trust enfoca federação (ativa) baseados em SOAP, como entre clientes do Windows e serviços do WCF.

Um cenário de federação passiva simples é ilustrado no do Figura 1.

image: A Simple Passive Federation Scenario

Figura 1 do Simple cenário de federação passivo A

Os usuários se autenticar seu domínio e recebem acesso a um aplicativo da Web de acordo com suas funções. Os participantes nesse esquema de autenticação incluem o usuário (o assunto), um navegador da Web (o solicitante), um aplicativo asp.net, a terceira parte confiável (RP), um IdP responsável por autenticar usuários em seu domínio e um STS que pertencem ao domínio do usuário (IP-STS). Uma seqüência de redirecionamentos de navegador garante que o usuário é autenticado em seu domínio antes de acessar a RP.

O usuário navega para o aplicativo da RP (1) e for redirecionado para sua IdP para ser autenticado (2). Se o usuário ainda não foi autenticado com o IdP, o IP-STS pode representar um desafio ou redirecionar a ela uma página de logon para coletar credenciais (3). O usuário fornece credenciais do usuário (4) e é autenticado por IP-STS (5). Neste ponto, o IP-STS emite um token de segurança de acordo com a solicitação de início de sessão e a resposta de sinal que contém o token é lançada para a RP via redirecionamento do navegador (6). A RP processa o token de segurança e autoriza o acesso com base em declarações que ele executa (7). Se a autorização bem-sucedida, é apresentada ao usuário com a página que originalmente solicitada por ela e um cookie de sessão é retornado (8).

Implementar este cenário de federação passiva com asp.net e o WIF envolve apenas algumas etapas:

  1. Estabelecer uma relação de confiança entre a RP e IdP (IP-STS)
  2. Habilitar a federação passiva para o aplicativo asp.NET
  3. Implemente autorização verifica para controlar o acesso a recursos do aplicativo em que as próximas seções, abordarei os recursos do WIF que oferecem suporte a federação passiva, percorrerei as etapas para configurar este cenário simples e, em seguida, explore outras considerações práticas para esse e outros cenários.

Recursos do WIF para federação passiva

Antes de discutir a implementação, vou examinar os recursos do WIF especificamente útil para a federação de identidades nos aplicativos asp.net. Para começar com WIF fornece os seguintes módulos HTTP úteis:

  • WSFederationAuthenticationModule (FAM): Permite a federação com base no navegador, o redirecionamento para o STS apropriado para autenticação e emissão de token de manipulação e processar a resposta resultante entrar para alimentar o token de segurança emitido para um ClaimsPrincipal para ser usado para autorização. Este módulo também trata de outras mensagens de federação importantes como, por exemplo, solicitações de saída da rede.
  • SessionAuthenticationModule (SAM): Gerencia a sessão autenticada ao gerar o token de segurança de sessão que contém o ClaimsPrincipal, gravá-la em um cookie, gerenciar a vida útil do cookie de sessão e rehydrating ClaimsPrincipal do cookie quando ela é apresentada. Este módulo também mantém um cache de token de sessão local.
  • ClaimsAuthorizatonModule: Fornece um ponto de extensibilidade para instalar um ClaimsAuthorizationManager personalizado que pode ser úteis para verificações de acesso centralizado.
  • ClaimsPrincipalHttpModule: Cria um ClaimsPrincipal de sua identidade atual do usuário associada ao thread da solicitação. Além disso, fornece um ponto de extensibilidade para instalar um ClaimsAuthenticationManager personalizado que pode ser úteis para personalizar o ClaimsPrincipal para ser anexado ao thread da solicitação.

ClaimsPrincipalHttpModule é mais útil para aplicativos sem a federação passiva. Você pode considerar isso como uma ferramenta útil para implementar o modelo de segurança baseada em declarações de um aplicativo asp.NET antes da movimentação de federação passiva. Abordei essa técnica para o WCF no meu artigo anterior.

Os três módulos são normalmente usados em conjunto para federação passiva — embora ClaimsAuthorizationModule é opcional. A Figura 2 ilustra como esses módulos principais ajustam o pipeline de solicitação e suas funções em uma solicitação de autenticação federada típico.

image: WIF Components and HTTP Modules Engaged in Passive Federation

A Figura 2 de WIF componentes e módulos HTTP encaixado na federação passiva

Tendo em mente o fluxo da federação passiva de do Figura 1, quando o usuário navega pela primeira vez para uma página protegida na RP (1), será negado o acesso ao aplicativo. O FAM processa as solicitações não autorizadas, produz a mensagem de entrada e redireciona o usuário para o IP-STS (2). O IP-STS autentica o usuário (3), produz uma resposta de entrada que inclui o token de segurança emitido e redireciona o aplicativo da RP (4).

O FAM processa a resposta de entrada — assegurando que a resposta contém um token de segurança válido para o usuário autenticado — e hydrates um ClaimsPrincipal a partir do início de sessão-resposta (5). Este procedimento definirá o objeto de segurança para o thread de solicitação e HttpContext. O FAM, em seguida, usa o SAM para serializar as reivindicações de ­ principal para um cookie HTTP (6) que será apresentado com as solicitações subseqüentes durante a sessão do navegador. Se ClaimsAuthorizationModule estiver instalado, ele invocará o configurado ClaimsAuthorization ­ Manager, fornecendo uma oportunidade de executar acesso global verifica (7) contra o ClaimsPrincipal antes para acessar o recurso solicitado.

Depois que o recurso solicitado é apresentado, o controle de acesso pode ser implementado com controles de login asp.net tradicionais, verificações de IsInRole e (8) de solicitações de outro código personalizado que consulta o usuário.

Nas solicitações subseqüentes, o token de sessão é apresentado com o cookie gravado anteriormente pelo SAM (9). Dessa vez o SAM está ativado para validar o token de sessão e realimentar as reivindicações de ­ principal do token (10). O FAM não está ativada, a menos que a solicitação é uma resposta no início de sessão, uma solicitação de saída da rede, ou se o acesso for negado, o que pode acontecer se o token de sessão não está presente ou expirou.

Como esses módulos, há dois controles do asp.net, que também são úteis em federação passiva:

  • Controle de FederatedPassiveSignIn: Pode ser usado em vez do FAM se o aplicativo irá redirecionar todas as chamadas não autorizadas para uma página de login que hospeda esse controle somente quando a autenticação é necessária. Isso pressupõe que o usuário irá interagir com o sinal-no processo — útil nos cenários de autenticação step-up onde o usuário será solicitado a fornecer credenciais, possivelmente mais credenciais de login do original, conforme exigido pelo aplicativo. O controle manipula o redirecionamento para o STS, processando a resposta de entrada, inicializando o ClaimsPrincipal da resposta e o estabelecimento de uma sessão segura, utilizando a funcionalidade exposta pelo FAM e SAM.
  • Controle de FederatedPassiveSignInStatus: Esse controle oferece uma maneira interativa do usuário entrar ou agrupado de início de sessão fora do aplicativo de RP, incluindo suporte a saída da rede.

A Figura 3 ilustra como o fluxo de comunicação muda quando o controle FederatedPassiveSignIn for empregado. O aplicativo se baseia em autenticação de formulários para proteger os recursos e redirecionar para a página de login, que hospeda o controle (1). O usuário clica no controle FederatedPassiveSignIn (ou poderá ser redirecionado automaticamente para ela), que dispara um redirecionamento para o STS (2). A página de controle recebe a resposta do STS, contando com o FAM e o SAM para processar a resposta no início de sessão (3), alimentar Claims ­ principal e gravar o cookie de sessão (4). Quando o usuário é redirecionado para a página originalmente solicitada (5), o SAM está ativado para validar o cookie de sessão e alimentar o ClaimsPrincipal para a solicitação. Neste ponto, o ClaimsAuthorizationModule e essa página podem executar as verificações de autorização, conforme ilustrado no do Figura 2.

image: Passive Federation with the FederatedPassive­-SignIn Control

A Figura 3 federação passiva com o FederatedPassive ­-controle de entrada entrar

FAM e no SAM dependem do apropriado de segurança ­ tipo TokenHandler para processar os tokens de entrada. Quando uma resposta de entrada é recebida, o FAM itera por meio de SecurityTokenHandlerCollection olhando para o identificador de token correto para ler o token XML. Em um cenário federado ela geralmente estará Saml11Security ­ TokenHandler ou Saml2Security ­ TokenHandler — Embora outros formatos de símbolo podem ser utilizados se você adicionar manipuladores de token personalizados. Para o SAM SessionSecurity ­ TokenHandler é usado para processar o token de sessão associado com o cookie de sessão.

Várias configurações de modelo de identidade são importantes para o fluxo da federação passiva — e são usados para inicializar o FAM e o SAM e o controle FederatedPassiveSignIn (embora o último também expõe as propriedades configuráveis do designer do Visual Studio). Programaticamente, você pode fornecer uma instância do serviço ­ tipo de configuração do namespace Microsoft.IdentityModel.Configuration ou você pode fornecer configuração declarativa na seção <microsoft.identityModel>. Figura 4 resume as configurações de modelo de identidade, muitos dos quais serão discutidos nas seções subseqüentes.

Figura 4 do Resumo do Essential <microsoft.identityModel> elementos

Seção Descrição
<issuerNameRegistry> Especifique uma lista de emissores de certificados confiáveis. Esta lista é útil principalmente para validar a assinatura do token, de modo que os tokens assinados por certificados não confiáveis serão rejeitadas.
<audienceUris> Especifica uma lista de público válido URIs para tokens de entrada SAML. Pode ser desativada para permitir que qualquer URI, embora não recomendada.
<securityTokenHandlers> Personalizar definições de configuração de manipuladores de token ou fornecer manipuladores de token personalizados para controlar como os tokens são validados, autenticados e serializados.
<maximumClockSkew> Ajuste a diferença do horário permitido entre símbolos de servidores e aplicativos de validade do token. Desvio padrão é 5 minutos.
<certificateValidation> Controle como os certificados são validados.
<serviceCertificate> Fornece um certificado de serviço para descriptografar os tokens de entrada.
<claimsAuthenticationManager> Fornece um tipo personalizado de ClaimsAuthenticationManager para personalizar ou substituir o tipo de IClaimsPrincipal a ser anexada ao thread da solicitação.
<claimsAuthorizationManager> Fornece um tipo personalizado de ClaimsAuthorizationManager para controlar o acesso à funcionalidade de um componente central.
<federatedAuthentication> Fornece configurações específicas de federação passiva.

A ativação de federação passiva

WIF torna mais fácil de configurar a federação passiva para seus aplicativos asp.net. Um STS deve fornecer metadados de federação (conforme descrito na especificação WS-Federation) e WIF fornece uma federação Utility (FedUtil.exe), que usa metadados de federação para estabelecer confiança entre uma RP e um STS (entre outros recursos úteis para ambos os cenários de federação ativa e passiva). Você pode chamar FedUtil na linha de comando ou do Visual Studio clicando com o botão direito sobre o projeto RP e selecionando o STS Adicionar referência.

Você concluirá as seguintes etapas simples com o Assistente FedUtil:

  • A primeira página do assistente permite que você confirme o arquivo de configuração a ser modificada pelo assistente e o aplicativo da RP URI.
  • A segunda página solicita o caminho para o documento XML de metadados de federação do STS com os quais a RP irá estabelecer relação de confiança.
  • A terceira página permite que você pode fornecer um certificado a ser usada para descriptografar os tokens.
  • A página final mostra uma lista de declarações oferecidos pelo STS — que pode ser usado para planejar as decisões de controle de acesso, por exemplo.

Quando as etapas do assistente forem concluídas, FedUtil modifica o projeto para adicionar uma referência ao assembly Microsoft.IdentityModel. Ela também modifica a Web. config para instalar os módulos FAM e SAM e forneça definições de configuração de modelo de identidade para os módulos. O aplicativo agora oferece suporte a federação passiva e irá redirecionar as solicitações não autorizadas para o STS confiável.

Não há uma pressuposição aqui o STS tem conhecimento prévio da RP, assim, irá emitir tokens de usuários autenticados, tentando acessar a RP e claro que ele possui a chave pública a RP requer que o STS usar para criptografar tokens. Esta é uma maneira fácil de obter seus aplicativos asp.net configurados inicialmente para federação. É claro, é útil para saber como configurar isso partir do zero no caso de ajustes necessários e como ir além das configurações básicas habilitadas pelo assistente. Vou me concentrar na abordagem “ a partir do zero ” daqui no.

Sem o FedUtil, você precisa adicionar manualmente uma referência ao assembly Microsoft.IdentityModel e configurar manualmente o FAM e os módulos de SAM juntamente com as configurações de modelo de identidade necessários. Módulos HTTP são adicionados às duas seções: System. Web do Internet Information Services (IIS) 6 e system.webServer para IIS 7. Supondo que o aplicativo é hospedado no IIS 7, os módulos WIF são configurados da seguinte maneira:

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

Por padrão nesta configuração só irá proteger os recursos com extensões explicitamente mapeadas para ser manipulado pelo pipeline do asp.net (. aspx,. asax e assim por diante). Para proteger recursos adicionais com autenticação federada, você deve mapear essas extensões para o pipeline do asp.net no IIS, ou você pode definir runAllManagedModulesForAllRequests como verdadeiro em módulos de configuração (somente para o IIS 7) da seguinte maneira:

<modules runAllManagedModulesForAllRequests="true">

Para FAM Iniciar, você deve definir o modo de autenticação do asp.net como nenhum e negar aos usuários anônimos o acesso aos recursos do aplicativo:

<authentication mode="None" />

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

Ambos os módulos se baseiam nas definições de configuração de modelo de identidade descritas em do Figura 4, um exemplo típico é neste Figura 5 . A maioria dessas configurações é gerada para você por FedUtil, com exceção de certificateValidation e algumas das configurações em federatedAuthentication. Tipicamente recomendo usar o modo de validação do certificado PeerTrust – que significa que você adicione explicitamente todos os certificados, inclusive do emissor confiável, para o armazenamento do local do computador TrustedPeople de confiáveis.

A Figura 5 de de configuração do modelo de identidade de federação passiva

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

Você normalmente exigem HTTPS/SSL de federação passiva proteger o token emitido portador contra ataques man-in-the-middle e exigem HTTPS/SSL para os cookies de sessão. Por padrão, os cookies estão ocultas de script, mas é uma configuração importante, por isso, eu chamo check-out no do Figura 5.

Como as de nome e caminho do cookie, o nome padrão FedAuth, o caminho para o diretório de aplicativo. Ele pode ser útil especificar um nome exclusivo para o cookie, principalmente se muitos aplicativos de RP na solução compartilham o mesmo domínio. Por outro lado, você pode optar por especificar um caminho de genérico, quando você deseja que os cookies sejam compartilhadas por vários aplicativos no mesmo domínio.

Você normalmente usará FedUtil para configurar aplicativos asp.net de federação passiva usando FAM e no SAM e ajustar as configurações apropriadas de acordo com os requisitos da solução. Você também pode usar o controle PassiveFederationSignIn no lugar de FAM, conforme ilustrado no do Figura 3. O controle ou pode carregar as configurações da seção microsoft.identityModel ou você pode definir as propriedades diretamente sobre o controle.

A abordagem do controle é útil se você desejar que as solicitações não autorizadas a ser redirecionado para uma página de login onde o usuário pode explicitamente entrar clicando no controle, em vez de ter o FAM redirecionar automaticamente para o STS. Por exemplo, se o usuário pode pertencer a mais de um provedor de identidade (território primário), a página de logon pode fornecer um mecanismo para ela indicar seu território primário antes para redirecionar para o STS. Em breve, eu abordarei a descoberta de território primário.

Emissão de token de passivo

Como mencionado anteriormente, federação passiva depende de redirecionamentos HTTP GET e POST e o navegador para facilitar a comunicação entre o STS e a RP. Figura 6 mostra os parâmetros de solicitação primária envolvidas no início de sessão de resposta e solicitação de início de sessão durante esse processo.

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

Figura 6 de entrar principal solicitação e resposta parâmetros envolvidos nas solicitações de federação passiva

Quando o STS recebe a solicitação de início de sessão, irá verificar que sabe sobre a RP, marcando o parâmetro wtrealm em relação a sua lista de territórios RP conhecidos. Presumivelmente, o STS terá conhecimento prévio da RP, o certificado necessário para o token de criptografia e as expectativas em relação às declarações desejadas a serem incluídos no token emitido. A RP pode indicar que afirma que é necessário se ele fornece o parâmetro opcional wreq com uma solicitação completa sign-in e o STS pode opcionalmente respeitam essa lista ou decidir forma autônoma que alega conceder com base no usuário autenticado.

Em um cenário de federação simples como esse descrito em 1 Figura , há uma única RP e um IP-STS único responsável por autenticar usuários. Se o IP-STS autentica os usuários em um domínio do Windows, ele pode emitir declarações de função, como administrador, usuário ou convidado. Pressupõe-se que essas funções têm significado para a RP para autorização. A próxima seção, considerarei essas funções é suficiente e discutem as técnicas de autorização. A seguir, discutirei a transformação de declarações no RP para converter as declarações do STS para algo mais útil para autorização, conforme necessário.

Autorização baseada em declarações

Como discutido no meu artigo anterior, a segurança baseada em função no .NET Framework espera que uma entidade de segurança está associada a cada thread. A entidade de segurança com base em IPrincipal, encapsula a identidade do usuário autenticado em uma implementação IIdentity. WIF fornece tipos ClaimsPrincipal e ClaimsIdentity com base em IClaimsPrincipal e IClaimsIdentity (que, por fim, derivam de IPrincipal e IIdentity). Quando o FAM processa a resposta de entrada, ele hydrates um ClaimsPrincipal para o token de segurança emitido. Da mesma forma, o SAM hydrates um ClaimsPrincipal para o cookie de sessão. Este ClaimsPrincipal é o coração de WIF autorização para seu aplicativo asp.net.

Você pode usar qualquer uma das seguintes abordagens para autorização:

  • Use configurações específicas do local de autorização para restringir o acesso a diretórios ou recursos de aplicativos individuais.
  • Use controles de login do asp.net, tais como o controle LoginView, para controlar o acesso à funcionalidade.
  • Use o ClaimsPrincipal para realizar verificações de IsInRole dinâmicas (por exemplo, para ocultar ou mostrar elementos da interface do usuário dinâmica).
  • Use o tipo PrincipalPermission realizar demandas de permissão dinâmico ou o PrincipalPermissionAttribute se a demanda de permissão declarativas parece apropriada em um método específico.
  • Forneça um ClaimsAuthorizationManager personalizado para centralizar o acesso faz check-in de um único componente, mesmo antes de carregar o recurso solicitado.

Os primeiros três dessas opções contam com o método IsInRole exposto pelo tipo ClaimsPrincipal. Você deve selecionar uma função declaração de tipo de ajuste para a verificação IsInRole para que as declarações corretas serão usadas para controlar o acesso. O tipo de declaração de função padrão para WIF é:

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

Se o ClaimsPrincipal incluir declarações definidas, o tipo de declaração de função corresponderá o padrão. Posteriormente, abordarei as declarações de permissão no contexto da transformação de declarações. Quando eles são utilizados, você deve especificar o tipo de declaração de permissão como o tipo de declaração de função, de modo que IsInRole entrará em vigor.

Você pode controlar o acesso a diretórios ou páginas específicas globalmente a partir do arquivo Web. config. Na raiz do aplicativo, fornece uma marca de local, especificando o caminho para proteger, permitir que uma lista de funções aceitáveis e negar acesso a todos os outros usuários. A seguir permite que os administradores somente acessar os arquivos sob o diretório AdminOnly:

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

Como alternativa, você pode colocar uma Web. config em qualquer subpasta e especificar regras de autorização. Colocar a seguinte configuração no diretório AdminOnly atinge o mesmo resultado:

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

Para ocultar dinamicamente e mostrar os componentes da interface do usuário ou caso contrário, controlar o acesso a recursos em uma página, você pode aproveitar os recursos com base em função de controles, como o LoginView. No entanto, a maioria dos desenvolvedores prefere definir explicitamente propriedades de controle de acesso durante a página carregar para um controle mais granular de controle. Para fazer isso, você pode chamar o método IsInRole exposto pelo Claims ­ principal. Você pode acessar o objeto atual através da propriedade estática de thread. CurrentPrincipal da seguinte maneira:

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

Além de verificações explícitas de IsInRole no tempo de execução, você também pode escrever usando a segurança de demandas de permissão de baseada em função clássica ­ tipo de permissão. Você inicializar o tipo com a declaração de função necessários (o segundo parâmetro de construtor) e quando é chamada por solicitação, o método IsInRole do objeto atual é chamado. Uma exceção é lançada se a declaração não for encontrada:

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

Essa abordagem é útil para rejeitar uma solicitação com uma exceção quando as funções apropriadas não estão presentes.

Também é útil centralizar as verificações de autorização comuns a todos os recursos solicitados. Às vezes, se você tiver uma diretiva de controle de acesso — por exemplo, as regras armazenadas em um banco de dados — você pode usar um componente central para ler essas regras para controlar o acesso a recursos e funcionalidade. Para isso, WIF fornece um componente ClaimsAuthorizationManager que você pode estender. Lembre-se no meu artigo anterior que você pode configurar esse tipo de componente personalizado, na seção de modelo de identidade:

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

A Figura 7 ilustra um ClaimsAuthorizationManager personalizada que verifica a presença de declaração de nome e se o recurso solicitado está dentro do diretório AdminsOnly requer a declaração de função de administradores.

A Figura 7 de de implementação personalizada do ClaimsAuthorizationManager

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

O CustomClaimsAuthorizationManager prevalece sobre a verificação de ­ acesso para fornecer essa funcionalidade. Este método fornece um parâmetro do AuthorizationContext, que fornece informações sobre a ação de solicitação (para federação passiva é um verbo HTTP como, por exemplo, GET ou POST), o recurso solicitado um URI () e o Claims ­ principal, que ainda não está anexado ao thread de solicitação.

Transformação de declarações

Em geral, as declarações emitidas por IP-STS, embora úteis para descrever o usuário autenticado, não são relevantes para os requisitos de autorização da RP. Não é trabalho do IdP saber que tipo de funções, as permissões ou outro artefato refinado é necessário para autorização em cada RP. É a função do IdP para conceder as declarações que são relevantes para o domínio do provedor de identidade, declarações de IdP pode afirmar sobre o usuário autenticado.

Dessa forma, a RP pode precisar transformar declarações do IP-STS em algo mais relevantes para autorização. Isso implica que a RP pode mapear a identidade do usuário (por exemplo, nome de usuário ou UPN) para um conjunto de declarações RP. Supondo que as declarações de função de padrão de concessões IP-STS Figura 8 listas de permissão de um conjunto de possível alega que a RP pode emitir com base em cada declaração de função de entrada. O tipo de declaração de permissão pode ser um tipo de declaração personalizada definido pela RP, tais como:

urn:ClaimsAwareWebSite/2010/01/claims/permission

Um bom lugar para transformar declarações de entrada IP-STS é com um ClaimsAuthenticationManager personalizado. Você pode instalar um ClaimsAuthenticationManager personalizada adicionando o seguinte à seção microsoft.identityModel:

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

A Figura 9 mostra um exemplo CustomClaimsAuthenticationManager transforma as declarações de função entrada concedidas pelo IP-STS em declarações de permissão relevantes para a RP.

A Figura 8 de Transforming função pede a permissão de declarações no RP

Declaração de função Solicitações de permissão
Administradores Criar, ler, atualizar, excluir
Usuários Criar, ler, atualizar
Convidado Leitura

A Figura 9 do personalizado transformação de declarações no 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;
  }
}

Para verificações de IsInRole (conforme descrito anteriormente) para funcionar, você deve fornecer o tipo de declaração de permissão conforme o tipo de declaração de função. Do Figura 9, isso é especificado quando o ClaimsIdentity é construído, porque a RP está criando o ClaimsIdentity.

No caso onde os tokens de entrada SAML são a origem das declarações, você pode fornecer o tipo de declarações de função para o tipo de SecurityTokenHandler. A seguir ilustra como configurar declarativamente Saml11SecurityTokenHandler para usar o tipo de declaração de permissão conforme o tipo de declaração de função:

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

Manipuladores de token SAML possuem uma seção de samlSecurityTokenRequirement onde você pode fornecer uma configuração para o nome e tipo, junto com outras configurações relacionadas à validação do certificado e tokens do Windows de pedidos de função.

Descoberta de território base

Até aqui, eu ter voltado para um cenário de federação simples com um único IP-STS. Pressupõe-se que a RP sempre redirecionará para uma determinada IP-STS para autenticar usuários.

No mundo de federação, no entanto, a RP pode confiar em vários emissores de token de vários domínios. Um novo desafio se apresenta nesse caso porque a RP deve decidir quais IP-STS devem autenticar os usuários que solicitam acesso aos recursos. O domínio ao qual os usuários autenticados é conhecido como território de base do usuário e, portanto, esse processo é chamado de descoberta de território primário.

Existem vários mecanismos de que um aplicativo pode usar para a descoberta de território primário:

  • Como no exemplo atual, de território primário é conhecido em solicitações avançadas e assim por sempre serão redirecionadas para um determinado IP-STS.
  • Os usuários podem navegar para a RP de outro portal, que pode fornecer uma seqüência de caracteres de consulta para indicar o território primário para os usuários a partir desse portal.
  • A RP pode exigir a Terra de usuários em uma página de entrada específica para cada território primário. A página inicial pode assumir um determinado território primário.
  • A RP pode ser capaz de determinar o território primário pelo endereço IP da solicitação ou alguns outra heurística.
  • Se a RP não é possível determinar o território primário de uma das técnicas mencionado anteriormente, ele pode apresentar uma interface do usuário onde o usuário pode selecionar o território primário ou fornecer informações que ajudam a RP determinar isso.
  • Se a RP oferece suporte a cartões de informações, o cartão selecionado pode direcionar a autenticação para o território primário apropriado usando a federação ativa.
  • O WS-Federation descreve resumidamente como um pode implementar um serviço de descoberta para resolver o território primário, mas não há uma especificação bem definida para isso.

Não importa como o território primário é descoberto, o objetivo é redirecionar o usuário seja autenticado com o IP-STS correto. Há algumas possíveis cenários aqui. Em um cenário, a RP talvez precise definir dinamicamente o URI do emissor, para que a solicitação de início de sessão é enviada para o IP-STS correto. Nesse caso, a RP deverá listar todos os IP-STS confiável na seção trustedIssuers, por exemplo:

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

Além disso, você pode substituir o evento RedirectingToIdentityProvider exposto pelo FAM e, usando a heurística relevantes, determinar o URI correto para o STS. Para fazer isso, coloque o seguinte código na implementação 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");
  }
}

Outro cenário envolve o parâmetro de território primário (whr) com a solicitação de início de sessão para o STS principal. A RP, por exemplo, terá um STS de recursos (R-STS ou RP-STS) responsável pela transformação de declarações. O RP-STS não autenticar os usuários (não é um IdP), mas possui relações de confiança com um ou mais IdPs.

A RP tem uma relação de confiança com o RP-STS e sempre respeitarão tokens emitidos pela RP-STS. O RP-STS é responsável pelo redirecionamento para o IdP correto para cada solicitação. O RP-STS pode determinar o IP-STS correto para redirecionar para conforme mostrado no código que acabamos de descrever, mas uma outra opção é para a RP fornecer informações sobre o território primário, passando isso no parâmetro de território primário para o RP-STS. Nesse caso, a RP dinamicamente define o parâmetro de território primário:

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

O RP-STS usa esse parâmetro para redirecionar para o IP-STS correto e, em seguida, transforma as declarações do IP-STS em declarações relevantes para a RP.

Single Sign-on e único de saída

Serviço Single Sign-on e única saída da rede são partes importantes de federação. Serviço Single Sign-on é um recurso que permite que os usuários autenticados acessar vários aplicativos de RP durante a autenticação apenas uma vez. Única de saída da rede, como está implícito, facilita a saída de todos os aplicativos de RP e qualquer cadeia relevante do STS com uma única solicitação.

Em uma federação simples cenário como aquele mostrado na 1 Figura , o usuário autentica para o IP-STS e está autorizado a RP com base no token de segurança emitido. POST-Authentication, o usuário tem um cookie de sessão para o STS e outro para a RP. Agora, se o usuário navega para outro RP, ela será redirecionada para o IP-STS para autenticação — supondo que os dois aplicativos de RP confia o mesmo IP-STS. Porque o usuário já possui uma sessão com o IP-STS, o STS emitirá um token para a RP segunda sem pedir credenciais. Agora, o usuário tem acesso para o segundo RP e tem um cookie de sessão novo para a RP de segunda.

Como já abordei WIF fornece o SAM para gravar o cookie de sessão para usuários autenticados. Por padrão, esse cookie de sessão é emitido para o endereço relativo de aplicativo para o domínio e seu nome de base é FedAuth. Como os cookies de sessão agrupada podem ser grandes, o token de geralmente é dividido em duas (ou mais) cookies: FedAuth, FedAuth1 e assim por diante.

Se você estiver hospedando a mais de um aplicativo no mesmo domínio, como parte do cenário de federação, o comportamento padrão pode ser que o navegador tenha um cookie FedAuth para cada RP (consulte do Figura 10). O navegador envia somente essas cookies associados com o domínio e o caminho para a solicitação.

image: Session Cookies Associated with Each RP and the STS

A Figura 10 de cookies de sessão associados com cada RP e o STS

Esse comportamento padrão é geralmente tudo bem, mas às vezes, é necessário fornecer um nome exclusivo por aplicativo para cada cookie por sessão – em especial se eles esteja hospedados no mesmo domínio. Ou vários aplicativos no mesmo domínio podem compartilhar um cookie de sessão, caso em que você pode definir o caminho do cookie para “ / ”.

Se o cookie de sessão expira, o navegador irá removê-lo do cache e o usuário será redirecionado novamente para o STS para autenticação. Separadamente, se o token emitido associado com o cookie de sessão expirou, WIF redirecionará para o STS para um novo token.

Saída da rede é mais explícita — geralmente orientada pelo usuário. Única saída da rede é um recurso opcional da especificação WS-Federation, que sugere o STS também deve notificar outros aplicativos de RP para os quais ele tem tokens emitidos da solicitação de saída da rede. Dessa forma, o cookie de sessão é removido para todos os aplicativos que o usuário tiver navegado até durante a sessão de logon única. Em um cenário mais complexo, onde vários STSs estão envolvidos, o STS principal recebe a solicitação de saída da rede também devem notificar outros STSs para fazer o mesmo.

Para fins de discussão, me concentrarei no que fazer em RP para facilitar a federados único de saída da rede. Você pode colocar o controle FederatedPassiveSignInStatus em qualquer página do qual você deseja oferecer suporte a entrada e saída da rede e o controle automaticamente irá indicar seu estado. Uma vez conectado-in, o controle apresenta um link, botão ou imagem de assinatura de check-out.

Quando você clica no controle, ele manipulará de acordo com para a propriedade SignOutAction, qual é possível atualizar, o redirecionamento, RedirectToLoginPage ou FederatedPassiveSignOut saída da rede. Os três primeiros excluir o cookie de sessão para o aplicativo, mas não informam o STS da solicitação de saída da rede. Quando você seleciona a configuração de FederatedPassiveSignOut, o controle chamará SignOut em WSFederationAuthenticationModule. Isso garante que os cookies de sessão agrupados são removidos do aplicativo. Além disso, uma solicitação de saída é enviada para o STS:

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

Se você não estiver usando o controle FederatedPassiveSignInStatus, você pode chamar diretamente o WSFederationAuthenticationModule.SignOut para disparar um redirecionamento para o STS com a solicitação de saída da rede.

Única saída da rede implica que o usuário está conectado de todos os aplicativos que conectou-se com sua identidade federada. Se o STS oferece suporte a isso, ele deve armazenar uma lista de aplicativos de RP o usuário fez logon durante sua sessão e o problema é solicitada uma solicitação de limpeza a cada RP quando agrupados saída da rede:

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

Em cenários mais complexos, a mesma solicitação de limpeza deve ser enviada para qualquer outros STS envolvida na sessão federada.Para esse fim, o STS teria que ter conhecimento prévio do URI de limpeza para cada RP e um STS.Para oferecer suporte a única saída da rede, seu RPs deve ser capaz de processar essas solicitações de limpeza.O FAM e o controle FederatedPassiveSignInStatus suportam isso.Se você estiver usando o FAM, a solicitação de limpeza pode ser lançada para qualquer URI de RP e o FAM irá processar a solicitação e limpar os cookies de sessão.Se você estiver usando o controle FederatedPassiveSignInStatus, a solicitação de limpeza deve ser lançada para uma página que contém o controle.

Na verdade, a especificação WS-Federation não detalhes sobre como implementar o comportamento de saída da rede e limpeza único além dos recomendados seqüências de caracteres e fluxo de comunicação.Não é fácil de garantir a única saída da rede será eficaz em todos os parceiros de federação como resultado, mas se você possuir o ambiente e deseja atingir esse objetivo, é possível que de fato.

Michele Leroux Bustamante é chefe de arquitetura na IDesign (idesign.net) e arquiteto-chefe de segurança em BiTKOO (bitkoo.com). Além disso, ela é um diretor regional da Microsoft de San Diego e MVP da Microsoft para sistemas conectados. Visite seu blog em dasblonde.net de .

Meus agradecimentos aos seguinte especialista técnico para revisar este artigo: Govind Ramanathan