Partager via


Comment : créer un service de jeton de sécurité

Un service de jeton de sécurité implémente le protocole défini dans la spécification WS-Trust. Ce protocole définit des formats de message et des modèles d'échange de message pour émettre, renouveler, annuler et valider des jetons de sécurité. Un service de jeton de sécurité donné fournit une ou plusieurs de ces fonctions. Cette rubrique examine le scénario le plus courant : l'implémentation de l'émission de jeton.

Émission de jetons

La spécification WS-Trust définit des formats de message, basés sur l'élément de schéma XSD (XML Schema Definition) RequestSecurityToken et sur l'élément de schéma XSD RequestSecurityTokenResponse pour réaliser une émission de jetons. De plus, elle définit les URI (Uniform Resource Identifier) d'action associés. L'URI d'action associé au message RequestSecurityToken est https://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue. L'URI d'action associé au message RequestSecurityTokenResponse est https://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue.

Structure d'un message de demande

La structure d'un message de demande d'émission se compose en général des éléments suivants :

De plus, plusieurs autres éléments peuvent être présents :

  • Le matériel de clé fourni par le client.

  • Des informations d'étendue qui indiquent avec quel service cible le jeton émis sera utilisé.

Le service de jeton de sécurité utilise les informations incluses dans le message de demande d'émission lorsqu'il construit le message de réponse d'émission.

Structure d'un message de réponse

La structure d'un message de réponse d'émission se compose en général des éléments suivants :

  • Le jeton de sécurité émis, par exemple, une assertion SAML 1.1.

  • Un jeton de preuve associé au jeton de sécurité. Pour des clés symétriques, il s'agit souvent d'une forme chiffrée du matériel de clé.

  • Des références au jeton de sécurité émis. En général, le service de jeton de sécurité retourne une référence qui peut être utilisée lorsque le jeton émis apparaît dans un message ultérieur envoyé par le client et une autre référence qui peut être utilisée lorsque le jeton n'est pas présent dans les messages ultérieurs.

De plus, plusieurs autres éléments peuvent être présents :

  • Le matériel de clé fourni par le service de jeton de sécurité.

  • L'algorithme requis pour calculer la clé partagée.

  • Les informations de durée de vie du jeton émis.

Traitement des messages de demande

Le service de jeton de sécurité traite la demande d'émission en examinant les différents éléments du message de demande et en s'assurant qu'il peut émettre un jeton satisfaisant la demande. Le service de jeton de sécurité doit déterminer les éléments suivants avant de créer le jeton à émettre :

  • La demande est vraiment une demande d'émission de jeton.

  • Le service de jeton de sécurité prend en charge le type de jeton demandé.

  • Le demandeur est autorisé à faire la demande.

  • Le service de jeton de sécurité peut satisfaire les attentes du demandeur en ce qui concerne le matériel de clé.

Deux parties essentielles de la construction d'un jeton correspondent à la détermination de la clé utilisée pour signer le jeton et de la clé utilisée pour chiffrer la clé partagée. Le jeton doit être signé pour que, lorsque le client présente le jeton au service cible, ce service puisse déterminer que le jeton a été émis par un service de jeton de sécurité qu'il approuve. Le matériel de clé doit être chiffré de telle façon que le service cible puisse le déchiffrer.

La signature d'une assertion SAML implique la création d'une instance SigningCredentials. Le constructeur pour cette classe utilise les éléments suivants :

  • Un SecurityKey pour la clé à utiliser pour signer l'assertion SAML.

  • Une chaîne qui identifie l'algorithme de signature à utiliser.

  • Une chaîne qui identifie l'algorithme Digest à utiliser.

  • En option, un SecurityKeyIdentifier qui identifie la clé à utiliser pour signer l'assertion.

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

Le chiffrement de la clé partagée implique le traitement du matériel de clé et son chiffrement avec une clé que le service cible peut utiliser pour déchiffrer la clé partagée. En général, la clé publique du service cible est utilisée.

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

De plus, un objet SecurityKeyIdentifier pour la clé chiffrée est requis.

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

}

Ensuite, cet objet SecurityKeyIdentifier est utilisé pour créer un SamlSubject dans le cadre du 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);
}

Pour plus d'informations, consultez Federation, exemple.

Création de messages de réponse

Une fois que le service de jeton de sécurité traite la demande d'émission et construit le jeton à émettre avec la clé de vérification, le message de réponse doit être construit, qui inclut au moins le jeton demandé, le jeton de preuve et des références au jeton émis. Le jeton émis est en général un SamlSecurityToken créé à partir de SamlAssertion, comme le montre l'exemple ci-dessous.

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

Dans le cas où le service de jeton de sécurité fournit le matériel de clé partagée, le jeton de preuve est construit en créant un BinarySecretSecurityToken.

Function CreateProofToken(ByVal proofKey() As Byte) As BinarySecretSecurityToken
    Return New BinarySecretSecurityToken(proofKey)

End Function
BinarySecretSecurityToken CreateProofToken(byte[] proofKey)
{
    return new BinarySecretSecurityToken(proofKey);
}

Pour plus d'informations sur le sujet suivant la façon de construire le jeton de preuve lorsque le client et le service de jeton de sécurité fournissent tous les deux du matériel de clé pour la clé partagée, consultez Federation, exemple.

Les références au jeton émis sont construites en créant des instances de la classe SecurityKeyIdentifierClause.

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

Ensuite, ces différentes valeurs sont sérialisées dans le message de réponse retourné au client.

Exemple

Pour obtenir le code complet pour un service de jeton de sécurité, consultez Federation, exemple.

Voir aussi

Tâches

Federation, exemple

Référence

SigningCredentials
SecurityKey
SecurityKeyIdentifier
SamlSecurityToken
SamlAssertion
BinarySecretSecurityToken
SecurityKeyIdentifierClause