Cómo: Crear un servicio de token de seguridad
Un servicio de token de seguridad implementa el protocolo definido en la especificación de WS-Trust. Este protocolo define formatos de mensaje y modelos de intercambio de mensajes para emitir, renovar, cancelar y validar tokens de seguridad. Un servicio de token de seguridad determinado proporciona uno o más de estas funciones. Este tema aborda el escenario común: implementación de la emisión de token.
Emitir tokens
WS-Trust define los formatos de mensaje, basándose en el elemento de esquema del lenguaje de definición de esquemas XML (XSD) RequestSecurityToken y en el elemento de esquema XSD RequestSecurityTokenResponse para realizar la emisión del token. Además, define los URI (Uniform Resource Identifier) de acción. El URI de acción asociado al mensaje RequestSecurityToken es https://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue. El URI de acción asociado al mensaje RequestSecurityTokenResponse es https://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue.
Estructura de mensaje de solicitud
La estructura del mensaje de solicitud de problema está normalmente compuesta de los elementos siguientes:
Un URI del tipo de petición con un valor de https://schemas.xmlsoap.org/ws/2005/02/trust/Issue.
Un URI del tipo de token. Para tokens de Security Assertions Markup Language (SAML) 1.1, el valor de este URI es http://docs.oasis open.org/wss/oasis wss saml #SAMLV1.1.
Un valor de tamaño clave que indica el número de bits en la clave que se va asociar al token emitido.
Un tipo URI clave. Para las claves simétricas, el valor de este URI es https://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey.
Además, un par de otros elementos podrían estar presentes:
Material clave proporcionado por el cliente.
Información de ámbito que indica el servicio de destino con el que se utilizará el token emitido.
El servicio de token de seguridad utiliza la información en el mensaje de solicitud del problema cuando construye el mensaje de respuesta del problema.
Estructura del mensaje de respuesta
La estructura del mensaje de respuesta del problema está normalmente compuesta de los elementos siguientes;
El token de seguridad emitido, por ejemplo, una aserción SAML 1.1.
Un token de prueba asociado al token de seguridad. Para las claves simétricas, éste es a menudo una forma cifrada del material clave.
Hace referencia al token de seguridad emitido. Normalmente, el servicio del token de seguridad devuelve una referencia que se puede utilizar cuando el token emitido aparece en un mensaje subsiguiente enviado por el cliente y otro que se puede utilizar cuando el token no se encuentra presente en mensajes subsiguientes.
Además, un par de otros elementos podrían estar presentes:
Material clave proporcionado por el servicio del token de seguridad.
El algoritmo necesario para calcular la clave compartida.
Información de duración del token emitido.
Procesar los mensajes de solicitud
El servicio del token de seguridad procesa la solicitud del problema examinando las varias partes del mensaje de solicitud y asegurándose de que puede emitir un token que satisfaga la solicitud. El servicio del token de seguridad debe determinar lo siguiente antes de construir el token que se va a emitir:
La solicitud realmente es una solicitud para un token que se va a emitir.
El servicio del token de seguridad soporta el tipo de token solicitado.
El solicitante está autorizado para realizar la solicitud.
El servicio del token de seguridad puede satisfacer las expectativas del solicitante con respecto al material clave.
Dos partes vitales de la construcción de un token determinan con qué clave se firmará el token y con qué clave se cifrará la clave compartida. El token debe ser firmado para que cuando el cliente presenta el token al servicio de destino, ese servicio pueda determinar que el token fue emitido por un servicio del token de seguridad en el que confía. El material clave debe cifrarse de manera que el servicio de destino pueda descifrar ese material de clave.
La firma de una aserción SAML implica la creación de una instancia SigningCredentials. El constructor para esta clase toma lo siguiente:
SecurityKey para que la clave lo utilice para firmar la aserción SAML.
Una cadena que identifica el algoritmo de firma a utilizar.
Una cadena que identifica el algoritmo de resumen a utilizar.
Opcionalmente, SecurityKeyIdentifier que identifica la clave a utilizar para firmar la aserción.
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
void AddSigningCredentials(SamlAssertion assertion, SecurityKey signingKey)
{
SigningCredentials sc = new SigningCredentials(signingKey,
SecurityAlgorithms.RsaSha1Signature, SecurityAlgorithms.Sha1Digest);
assertion.SigningCredentials = sc;
}
El cifrado de la clave compartida implica tomar el material clave y cifrarlo con una clave que el servicio de destino pueda utilizar para descifrar la clave compartida. Normalmente, se utiliza la clave pública del servicio de destino.
Function EncryptKey(ByVal plainTextKey() As Byte, _
ByVal encryptingKey As SecurityKey) As Byte()
Return encryptingKey.EncryptKey(SecurityAlgorithms.RsaOaepKeyWrap, plainTextKey)
End Function
byte[] EncryptKey(byte[] plainTextKey, SecurityKey encryptingKey)
{
return encryptingKey.EncryptKey(SecurityAlgorithms.RsaOaepKeyWrap, plainTextKey);
}
Además, se necesita SecurityKeyIdentifier para la clave cifrada.
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
SecurityKeyIdentifier GetKeyIdentifierForEncryptedKey(byte[] encryptedKey,
SecurityToken encryptingToken)
{
SecurityKeyIdentifier encryptingKeyIdentifier = new SecurityKeyIdentifier(encryptingToken.CreateKeyIdentifierClause<X509ThumbprintKeyIdentifierClause>());
return new SecurityKeyIdentifier(new EncryptedKeyIdentifierClause(encryptedKey, SecurityAlgorithms.RsaOaepKeyWrap, encryptingKeyIdentifier));
}
SecurityKeyIdentifier se utiliza a continuación para crear un SamlSubject como parte del SamlToken.
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
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);
}
Para obtener más información, vea Ejemplo de federación.
Crear los mensajes de respuesta
Cuando el servicio del token de seguridad procesa la solicitud del problema y construye el token que se va a emitir junto con la clave de prueba, el mensaje de respuesta necesita ser construido, incluyendo como mínimo el token solicitado, el token de prueba y las referencias del token emitido. El token emitido es normalmente SamlSecurityToken creado a partir de SamlAssertion, como se muestra en el ejemplo siguiente.
Function CreateIssuedToken(ByVal assertion As SamlAssertion) As SecurityToken
Return New SamlSecurityToken(assertion)
End Function
SecurityToken CreateIssuedToken(SamlAssertion assertion)
{
return new SamlSecurityToken(assertion);
}
En el caso donde el servicio del token de seguridad proporciona el material de la clave compartida, el token de prueba se construye creando BinarySecretSecurityToken.
Function CreateProofToken(ByVal proofKey() As Byte) As BinarySecretSecurityToken
Return New BinarySecretSecurityToken(proofKey)
End Function
BinarySecretSecurityToken CreateProofToken(byte[] proofKey)
{
return new BinarySecretSecurityToken(proofKey);
}
Sobre Para obtener más información sobre cómo construir el token de prueba cuando tanto el cliente como el servicio del token de seguridad proporcionan el material clave para la clave compartida, vea Ejemplo de federación.
Las referencias del token emitido se construyen creando instancias de la clase SecurityKeyIdentifierClause.
Function CreateTokenReference(ByVal token As SamlSecurityToken) _
As SecurityKeyIdentifierClause
Return token.CreateKeyIdentifierClause( _
Of SamlAssertionKeyIdentifierClause)()
End Function
SecurityKeyIdentifierClause CreateTokenReference(SamlSecurityToken token)
{
return token.CreateKeyIdentifierClause<SamlAssertionKeyIdentifierClause>();
}
Estos valores diferentes se serializan a continuación en el mensaje de respuesta devuelto al cliente.
Ejemplo
Para el código completo para un servicio del token de seguridad, vea Ejemplo de federación.
Vea también
Tareas
Referencia
SigningCredentials
SecurityKey
SecurityKeyIdentifier
SamlSecurityToken
SamlAssertion
BinarySecretSecurityToken
SecurityKeyIdentifierClause