Partilhar via


Como: Criar um serviço de token de segurança

Um serviço de token de segurança implementa o protocolo definido na especificação WS-Trust. Esse protocolo define formatos de mensagem e padrões de troca de mensagens para emissão, renovação, cancelamento e validação de tokens de segurança. Um determinado serviço de token de segurança fornece um ou mais desses recursos. Este tópico analisa o cenário mais comum: implementar a emissão de tokens.

Emissão de tokens

WS-Trust define formatos de mensagem, com base no elemento de esquema XSD (XML Schema Definition Language) e RequestSecurityTokenResponse no elemento de esquema XSD para executar a RequestSecurityToken emissão de token. Além disso, define os URIs (Action Uniform Resource Identifiers) associados. O URI de ação associado à RequestSecurityToken mensagem é http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue. O URI de ação associado à RequestSecurityTokenResponse mensagem é http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue.

Estrutura da mensagem de solicitação

A estrutura da mensagem de solicitação de problema geralmente consiste nos seguintes itens:

  • Um tipo de solicitação URI com um valor de http://schemas.xmlsoap.org/ws/2005/02/trust/Issue.

  • Um URI de tipo de token. Para tokens SAML (Security Assertions Markup Language) 1.1, o valor desse URI é http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1.

  • Um valor de tamanho de chave que indica o número de bits na chave a ser associada ao token emitido.

  • Um URI de tipo de chave. Para chaves simétricas, o valor desse URI é http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey.

Além disso, alguns outros itens podem estar presentes:

  • Material chave fornecido pelo cliente.

  • Informações de escopo que indicam o serviço de destino com o qual o token emitido será usado.

O serviço de token de segurança usa as informações na mensagem de solicitação de problema quando constrói a mensagem de resposta ao problema.

Estrutura da mensagem de resposta

A estrutura da mensagem de resposta ao problema normalmente consiste nos seguintes itens;

  • O token de segurança emitido, por exemplo, uma asserção SAML 1.1.

  • Um token de prova associado ao token de segurança. Para chaves simétricas, esta é muitas vezes uma forma encriptada do material da chave.

  • Referências ao token de segurança emitido. Normalmente, o serviço de token de segurança retorna uma referência que pode ser usada quando o token emitido aparece em uma mensagem subsequente enviada pelo cliente e outra que pode ser usada quando o token não está presente em mensagens subsequentes.

Além disso, alguns outros itens podem estar presentes:

  • Material chave fornecido pelo serviço de token de segurança.

  • O algoritmo necessário para calcular a chave compartilhada.

  • Informações vitalícias para o token emitido.

Processando mensagens de solicitação

O serviço de token de segurança processa a solicitação de problema examinando as várias partes da mensagem de solicitação e garantindo que ele possa emitir um token que satisfaça a solicitação. O serviço de token de segurança deve determinar o seguinte antes de construir o token a ser emitido:

  • O pedido é realmente um pedido para que um token seja emitido.

  • O serviço de token de segurança suporta o tipo de token solicitado.

  • O requerente está autorizado a fazer o pedido.

  • O serviço de token de segurança pode atender às expectativas do solicitante em relação ao material de chave.

Duas partes vitais da construção de um token são determinar com qual chave assinar o token e com qual chave criptografar a chave compartilhada. O token precisa ser assinado para que, quando o cliente apresentar o token ao serviço de destino, esse serviço possa determinar que o token foi emitido por um serviço de token de segurança confiável. O material de chave precisa ser criptografado de tal forma que o serviço de destino possa descriptografar esse material de chave.

A assinatura de uma asserção SAML envolve a criação de uma SigningCredentials instância. O construtor para esta classe leva o seguinte:

  • A SecurityKey para a chave a ser usada para assinar a asserção SAML.

  • Uma cadeia de caracteres que identifica o algoritmo de assinatura a ser usado.

  • Uma cadeia de caracteres que identifica o algoritmo digest a ser usado.

  • Opcionalmente, um SecurityKeyIdentifier que identifica a chave a ser usada para assinar a asserção.

void AddSigningCredentials(SamlAssertion assertion, SecurityKey signingKey)
{
    SigningCredentials sc = new SigningCredentials(signingKey,
        SecurityAlgorithms.RsaSha1Signature, SecurityAlgorithms.Sha1Digest);
    assertion.SigningCredentials = sc;
}
Sub AddSigningCredentials(ByVal assertion As SamlAssertion, _
    ByVal signingKey As SecurityKey)
    Dim sc As New SigningCredentials(signingKey, _
    SecurityAlgorithms.RsaSha1Signature, SecurityAlgorithms.Sha1Digest)
    assertion.SigningCredentials = sc

End Sub

Criptografar a chave compartilhada envolve pegar o material da chave e criptografá-lo com uma chave que o serviço de destino pode usar para descriptografar a chave compartilhada. Normalmente, a chave pública do serviço de destino é usada.

byte[] EncryptKey(byte[] plainTextKey, SecurityKey encryptingKey)
{
    return encryptingKey.EncryptKey(SecurityAlgorithms.RsaOaepKeyWrap, plainTextKey);
}
Function EncryptKey(ByVal plainTextKey() As Byte, _
        ByVal encryptingKey As SecurityKey) As Byte()
    Return encryptingKey.EncryptKey(SecurityAlgorithms.RsaOaepKeyWrap, plainTextKey)
End Function

Além disso, é necessário um SecurityKeyIdentifier para a chave encriptada.

SecurityKeyIdentifier GetKeyIdentifierForEncryptedKey(byte[] encryptedKey,
    SecurityToken encryptingToken)
{
    SecurityKeyIdentifier encryptingKeyIdentifier = new SecurityKeyIdentifier(encryptingToken.CreateKeyIdentifierClause<X509ThumbprintKeyIdentifierClause>());
    return new SecurityKeyIdentifier(new EncryptedKeyIdentifierClause(encryptedKey, SecurityAlgorithms.RsaOaepKeyWrap, encryptingKeyIdentifier));
}
Function GetKeyIdentifierForEncryptedKey(ByVal encryptedKey() _
 As Byte, ByVal encryptingToken As SecurityToken) _
    As SecurityKeyIdentifier
    Dim encryptingKeyIdentifier As New SecurityKeyIdentifier( _
        encryptingToken.CreateKeyIdentifierClause(Of X509ThumbprintKeyIdentifierClause)())
    Return New SecurityKeyIdentifier(New EncryptedKeyIdentifierClause( _
        encryptedKey, SecurityAlgorithms.RsaOaepKeyWrap, encryptingKeyIdentifier))
End Function

Isso SecurityKeyIdentifier é usado para criar um SamlSubject como parte do SamlToken.

SamlSubject CreateSamlSubjectForProofKey(SecurityKeyIdentifier proofKeyIdentifier)
{
    List<string> confirmations = new List<string>();

    confirmations.Add("urn:oasis:names:tc:SAML:1.0:cm:holder-of-key");

    return new SamlSubject(null, null, "IssuerName", confirmations, null, proofKeyIdentifier);
}
Function CreateSamlSubjectForProofKey( _
    ByVal proofKeyIdentifier As SecurityKeyIdentifier) As SamlSubject
    Dim confirmations As List(Of String) = New List(Of String)()
    confirmations.Add("urn:oasis:names:tc:SAML:1.0:cm:holder-of-key")
    Return New SamlSubject(Nothing, Nothing, "IssuerName", _
        confirmations, Nothing, proofKeyIdentifier)
End Function

Para obter mais informações, consulte Exemplo de federação.

Criando mensagens de resposta

Depois que o serviço de token de segurança processa a solicitação de emissão e constrói o token a ser emitido junto com a chave de prova, a mensagem de resposta precisa ser construída, incluindo pelo menos o token solicitado, o token de prova e as referências de token emitidas. O token emitido é normalmente um SamlSecurityToken criado a SamlAssertionpartir do , conforme mostrado no exemplo a seguir.

SecurityToken CreateIssuedToken(SamlAssertion assertion)
{
    return new SamlSecurityToken(assertion);
}
Function CreateIssuedToken(ByVal assertion As SamlAssertion) As SecurityToken
    Return New SamlSecurityToken(assertion)
End Function

No caso em que o serviço de token de segurança fornece o material de chave compartilhada, o token de prova é construído criando um BinarySecretSecurityTokenarquivo .

BinarySecretSecurityToken CreateProofToken(byte[] proofKey)
{
    return new BinarySecretSecurityToken(proofKey);
}
Function CreateProofToken(ByVal proofKey() As Byte) As BinarySecretSecurityToken
    Return New BinarySecretSecurityToken(proofKey)

End Function

Para obter mais informações sobre como construir o token de prova quando o cliente e o serviço de token de segurança fornecem material de chave para a chave compartilhada, consulte Exemplo de federação.

As referências de token emitidas são construídas criando instâncias da SecurityKeyIdentifierClause classe.

SecurityKeyIdentifierClause CreateTokenReference(SamlSecurityToken token)
{
    return token.CreateKeyIdentifierClause<SamlAssertionKeyIdentifierClause>();
}
Function CreateTokenReference(ByVal token As SamlSecurityToken) _
    As SecurityKeyIdentifierClause
    Return token.CreateKeyIdentifierClause( _
    Of SamlAssertionKeyIdentifierClause)()
End Function

Esses vários valores são então serializados na mensagem de resposta retornada ao cliente.

Exemplo

Para obter o código completo para um serviço de token de segurança, consulte Exemplo de federação.

Consulte também