Condividi tramite


Procedura: creare un servizio token di sicurezza

Un servizio token di sicurezza implementa il protocollo definito nella specifica WS-Trust. Questo protocollo definisce i formati e i modelli di scambio dei messaggi per il rilascio, il rinnovo, l'annullamento e la convalida di token di sicurezza. Un determinato servizio token di sicurezza fornisce una o più di queste funzionalità. In questo argomento viene descritto lo scenario più comune: l'implementazione del rilascio di token.

Rilascio di token

Per l'esecuzione del rilascio del token WS-Trust definisce i formati dei messaggi in base all'elemento dello schema XSD (XML Schema Definition Language) di RequestSecurityToken e all'elemento dello schema XSD di RequestSecurityTokenResponse. Definisce inoltre gli URI (Uniform Resource Identifiers) dell'azione associati. L'URI dell'azione associato al messaggio RequestSecurityToken è https://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue. L'URI dell'azione associato al messaggio RequestSecurityTokenResponse è https://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue.

Struttura del messaggio di richiesta

In genere la struttura del messaggio di richiesta consiste negli elementi seguenti:

Potrebbero inoltre essere presenti altri elementi:

  • Materiale della chiave fornito dal client.

  • Informazioni di ambito che indicano il servizio di destinazione con il quale verrà utilizzato il token rilasciato.

Il servizio token di sicurezza utilizza le informazioni contenute nel messaggio di richiesta di rilascio quando costruisce il messaggio di risposta del rilascio.

Struttura del messaggio di risposta

In genere la struttura del messaggio di risposta consiste negli elementi seguenti:

  • Token di sicurezza rilasciato, ad esempio un'asserzione SAML 1.1.

  • Token di prova associato al token di sicurezza. Per le chiavi simmetriche spesso si tratta della forma crittografata del materiale della chiave.

  • Riferimenti al token di sicurezza rilasciato. In genere, il servizio token di sicurezza restituisce un riferimento che può essere utilizzato quando il token rilasciato ricorre in un messaggio successivo inviato dal client e un altro riferimento che può essere utilizzato quando il token non è presente nei messaggi successivi.

Potrebbero inoltre essere presenti altri elementi:

  • Materiale della chiave fornito dal servizio token di sicurezza.

  • Algoritmo necessario per calcolare la chiave condivisa.

  • Informazioni sulla durata per il token rilasciato.

Elaborazione dei messaggi di richiesta

Il servizio token di sicurezza elabora la richiesta di rilascio esaminando i vari elementi del messaggio di richiesta e valutando la possibilità di rilasciare un token che soddisfi la richiesta. Il servizio token di sicurezza deve determinare quanto segue prima di costruire il token da rilasciare:

  • La richiesta riguarda effettivamente il rilascio di un token.

  • Il servizio token di sicurezza supporta il tipo di token richiesto.

  • Il richiedente è autorizzato a eseguire la richiesta.

  • Il servizio token di sicurezza può soddisfare le aspettative del richiedente in merito al materiale della chiave.

Due punti fondamentali nella costruzione di un token consistono nello stabilire la chiave con la quale firmare il token e la chiave con la quale crittografare la chiave condivisa. È necessario che il token venga firmato affinché, quando il client presenta il token al servizio di destinazione, quest'ultimo sia in grado di appurare che il token è stato rilasciato da un servizio token di sicurezza affidabile. Il materiale della chiave deve essere crittografato in modo tale da consentire al servizio di destinazione di decrittografarlo.

La firma di un'asserzione SAML implica la creazione di un'istanza SigningCredentials. Il costruttore di questa classe accetta quanto segue:

  • Un elemento SecurityKey che la chiave utilizza per firmare l'asserzione SAML.

  • Una stringa che identifica l'algoritmo della firma da utilizzare.

  • Una stringa che identifica l'algoritmo di digest da utilizzare.

  • Facoltativamente un elemento SecurityKeyIdentifier che identifica la chiave da utilizzare per firmare l'asserzione.

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

La crittografia della chiave condivisa comporta la crittografia del materiale della chiave con una chiave che il servizio di destinazione può utilizzare per decrittografare la chiave condivisa. In genere viene utilizzata la chiave pubblica del servizio di destinazione.

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

È inoltre necessario un elemento SecurityKeyIdentifier per la chiave crittografata.

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

}

L'oggetto SecurityKeyIdentifier viene quindi utilizzato per creare SamlSubject come parte di 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);
}

Per ulteriori informazioni, vedere Esempio di federazione.

Creazione dei messaggi di risposta

Terminata l'elaborazione della richiesta di rilascio da parte del servizio token di sicurezza e conclusa la costruzione del token da rilasciare unitamente alla chiave di prova, è necessario costruire il messaggio di risposta, che deve comprendere almeno il token richiesto, il token di prova e i riferimenti del token rilasciato. Il token rilasciato è in genere un SamlSecurityToken creato da SamlAssertion, come illustrato nell'esempio seguente.

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

Nel caso in cui il servizio token di sicurezza fornisca il materiale della chiave condivisa, il token di prova viene costruito creando un elemento BinarySecretSecurityToken.

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

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

Per ulteriori informazioni su su come costruire il token di prova quando il client e il servizio token di sicurezza forniscono entrambi materiale per la chiave condivisa, vedere Esempio di federazione.

I riferimenti del token rilasciato sono costruiti creando istanze della 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>();
}

Tutti questi diversi valori vengono quindi serializzati nel messaggio di risposta restituito al client.

Esempio

Per il codice completo di un servizio token di sicurezza, vedere Esempio di federazione.

Vedere anche

Attività

Esempio di federazione

Riferimento

SigningCredentials
SecurityKey
SecurityKeyIdentifier
SamlSecurityToken
SamlAssertion
BinarySecretSecurityToken
SecurityKeyIdentifierClause