How to: Create a Security Token Manager for a Custom Security Token
WSE relies on security token managers for creating instances of security tokens based on an XML representation. Primarily this is necessary when WSE receives a SOAP message with security tokens. When the SOAP message is received, WSE can solicit the security token manager for an instance of a security token based on the XML content held within a WS-Security SOAP header. If the security token is one that WSE natively supports, such as Kerberos tickets or an X.509 certificate, WSE knows which security token manager to use. For custom XML security tokens, WSE needs to have a security token manager to call. This topic details how to create a security token manager for WSE to call. For more information about configuring a security token manager so that WSE knows how to call the correct security token manager, see How to: Configure the Security Token Manager for a Custom Security Token
To create a security token manager for a custom XML security token
Add a new class to the project containing the class representing the security token. Derive the class from the SecurityTokenManager class.
Public Class XmlTokenManager Inherits SecurityTokenManager
public class XmlTokenManager : SecurityTokenManager
Add the Imports statements or using directives shown in the following code example to the top of the file for the class.
Imports System Imports System.Security.Cryptography Imports System.Security.Cryptography.Xml Imports System.Security.Permissions Imports System.Text Imports System.Globalization Imports System.Xml Imports Microsoft.Web.Services2.Security Imports Microsoft.Web.Services2.Security.Tokens
using System; using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Permissions; using System.Text; using System.Globalization; using System.Xml; using Microsoft.Web.Services2.Security; using Microsoft.Web.Services2.Security.Tokens;
Implement the TokenType property.
The TokenType property is an XmlQualifiedName class that uniquely identifies the custom XML security token type for which this security token manager is able to create instances of security tokens from XML.
The following code example returns the XmlQualifiedName class for the custom XML security token.
Public Overrides ReadOnly Property TokenType() As XmlQualifiedName Get Return XmlToken.TokenValueType End Get End Property
public override XmlQualifiedName TokenType { get { return XmlToken.TokenValueType; } }
Implement the LoadTokenFromXml method, which deserializes an XML element into a security token.
The following code example calls the constructor that takes an XmlElement argument to deserialize the XmlElement class into an instance of the custom XML security token.
Public Overrides Function LoadTokenFromXml(element As XmlElement) As SecurityToken Return New XmlToken(element) End Function
public override SecurityToken LoadTokenFromXml(XmlElement element) { return new XmlToken(element); }
Implement the LoadTokenFromKeyInfo method.
The LoadTokenFromKeyInfo method is called by WSE to retrieve the decryption key for a custom XML security token.
Public Overrides Function LoadTokenFromKeyInfo(ByVal keyInfo As _ KeyInfo) As SecurityToken ' Verify that the keyInfo parameter contains a value. If keyInfo Is Nothing Then Throw New ArgumentNullException("keyInfo") End If Dim reference As SecurityTokenReference Dim clause As KeyInfoClause For Each clause In keyInfo reference = CType(clause, SecurityTokenReference) ' Check if the custom XML security token is the security ' token handled by this security token manager. If TypeOf clause Is SecurityTokenReference AndAlso _ reference.KeyIdentifier.ValueType.Equals( _ XmlToken.TokenValueType) Then ' If the custom XML security token is the security ' token managed by this security token manager, ' get the keys for the security token from the ' cryptographic key container specified in the ' KeyIdentifier property. Dim bytes As Byte() = reference.KeyIdentifier.Value Dim keyContainer As String = _ System.Text.Encoding.Default.GetString(bytes) ' Let the custom XML security token do the work of ' retrieving the key for the security token. Dim token As New XmlToken(keyContainer, True) Return token Else ' If this custom XML security token is not the ' one managed by this security token manager, let the ' default security token provider try to handle it. Return Nothing End If Next clause ' If execution reaches here, the custom XML security token ' could not be loaded. Return Nothing End Function
public override SecurityToken LoadTokenFromKeyInfo(KeyInfo keyInfo) { // Verify that the keyInfo parameter contains a value. if (null == keyInfo) throw new ArgumentNullException("keyInfo"); SecurityTokenReference reference; foreach ( KeyInfoClause clause in keyInfo ) { reference = (SecurityTokenReference)clause; // Check if the custom XML security token is the // security token handled by this security token manager. if ( clause is SecurityTokenReference && (reference.KeyIdentifier.ValueType == XmlToken.TokenValueType)) { // If the custom XML security token is the security // token managed by this security token manager, // get the keys for the security token from the cryptographic // key container specified in the KeyIdentifier property. byte[] bytes = reference.KeyIdentifier.Value; string keyContainer = System.Text.Encoding.Default.GetString(bytes); // Let the custom XML security token do the work of // retrieving the key for the security token. XmlToken token = new XmlToken(keyContainer, true); return token; } else { // If this custom XML security token is not the // one managed by this security token manager, let the // default security token provider try to handle it. return null; } } // If execution reaches here, the custom XML security token // could not be loaded. return null; }
Implement the VerifyToken method.
WSE calls the VerifyToken method after a custom XML security token is deserialized to verify whether the security token is still valid.
Public Overrides Sub VerifyToken(ByVal token As SecurityToken) Dim xmlToken As xmlToken = CType(token, xmlToken) If xmlToken Is Nothing Then Throw New ArgumentException( _ "The security token provided is not an XmlToken instance.", "token") ElseIf xmlToken.IsCurrent = False Then Throw New ApplicationException("The provided XmlToken security token has expired.") End If End Sub 'VerifyToken
public override void VerifyToken(SecurityToken token) { XmlToken xmlToken = token as XmlToken; if (xmlToken == null) { throw new ArgumentException( "The security token provided is not an XmlToken instance.", "token"); } else if (xmlToken.IsCurrent == false) { throw new ApplicationException("The provided XmlToken security token has expired."); } }
Example
The following code example is a security token manager for a custom XML security token.
Imports System
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Security.Permissions
Imports System.Text
Imports System.Globalization
Imports System.Xml
Imports Microsoft.Web.Services2.Security
Imports Microsoft.Web.Services2.Security.Tokens
Namespace CustomXmlSecToken
Public Class XmlTokenManager
Inherits SecurityTokenManager
Public Overrides ReadOnly Property TokenType() As _
XmlQualifiedName
Get
Return XmlToken.TokenValueType
End Get
End Property
' Return an instance of the security token that was serialized
' to an XML format.
Public Overrides Function LoadTokenFromXml( _
element As XmlElement) As SecurityToken
Return New XmlToken(element)
End Function
' Return a security token based on a KeyInfo clause.
Public Overrides Function LoadTokenFromKeyInfo( _
ByVal keyInfo As KeyInfo) As SecurityToken
' Verify that the keyInfo parameter contains a value.
If keyInfo Is Nothing Then
Throw New ArgumentNullException("keyInfo")
End If
Dim reference As SecurityTokenReference
Dim clause As KeyInfoClause
For Each clause In keyInfo
reference = CType(clause, SecurityTokenReference)
' Check if the custom XML security token is the security
' token handled by this security token manager.
If TypeOf clause Is SecurityTokenReference AndAlso _
reference.KeyIdentifier.ValueType.Equals( _
XmlToken.TokenValueType) Then
' If the custom XML security token is the security
' token managed by this security token manager,
' get the keys for the security token from the
' cryptographic key container specified in the
' KeyIdentifier property.
Dim bytes As Byte() = reference.KeyIdentifier.Value
Dim keyContainer As String = _
System.Text.Encoding.Default.GetString(bytes)
' Let the custom XML security token do the work of
' retrieving the key for the security token.
Dim token As New XmlToken(keyContainer, True)
Return token
Else
' If this custom XML security token is not the
' one managed by this security token manager, let
' the default security token provider try to handle
' it.
Return Nothing
End If
Next clause
' If execution reaches here, the custom XML security
' token could not be loaded.
Return Nothing
End Function
' WSE calls the VerifyToken method after a custom XML security token
' is deserialized to verify whether the security token is still
' valid.
Public Overrides Sub VerifyToken(ByVal token As SecurityToken)
Dim xmlToken As xmlToken = CType(token, xmlToken)
If xmlToken Is Nothing Then
Throw New ArgumentException( _
"The security token provided is not an XmlToken instance.", "token")
ElseIf xmlToken.IsCurrent = False Then
Throw New ApplicationException("The provided XmlToken security token has expired.")
End If
End Sub
End Class
End Namespace
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Permissions;
using System.Text;
using System.Globalization;
using System.Xml;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
namespace CustomXmlSecToken
{
public class XmlTokenManager : SecurityTokenManager
{
public override XmlQualifiedName TokenType
{
get
{
return XmlToken.TokenValueType;
}
}
// The LoadTokenFromXml method deserializes an XML element into
// a security token.
public override SecurityToken LoadTokenFromXml(XmlElement
element)
{
return new XmlToken(element);
}
// Return a security token based on a KeyInfo clause.
public override SecurityToken LoadTokenFromKeyInfo(KeyInfo keyInfo)
{
// Verify that the keyInfo parameter contains a value.
if (null == keyInfo)
throw new ArgumentNullException("keyInfo");
SecurityTokenReference reference;
foreach ( KeyInfoClause clause in keyInfo )
{
reference = (SecurityTokenReference)clause;
// Check if the custom XML security token is the
// security token handled by this security token
// manager.
if ( clause is SecurityTokenReference &&
(reference.KeyIdentifier.ValueType ==
XmlToken.TokenValueType))
{
// If the custom XML security token is the security
// token managed by this security token manager,
// get the keys for the security token from the
// cryptographic key container specified in the
// KeyIdentifier property.
byte[] bytes = reference.KeyIdentifier.Value;
string keyContainer =
System.Text.Encoding.Default.GetString(bytes);
// Let the custom XML security token do the work of
// retrieving the key for the security token.
XmlToken token = new XmlToken(keyContainer, true);
return token;
}
else
{
// If this custom XML security token is not the
// one managed by this security token manager, let
// the default security token provider try to
// handle it.
return null;
}
}
// If execution reaches here, the custom XML
// security token could not be loaded.
return null;
}
// WSE calls the VerifyToken method after a custom XML security token
// is deserialized to verify whether the security token is
// still valid.
public override void VerifyToken(SecurityToken token)
{
XmlToken xmlToken = token as XmlToken;
if (xmlToken == null)
{
throw new ArgumentException(
"The security token provided is not an XmlToken instance.", "token");
}
else if (xmlToken.IsCurrent == false)
{
throw new ApplicationException("The provided XmlToken security token has expired.");
}
}
}
}
See Also
Tasks
How to: Configure the Security Token Manager for a Custom Security Token
How to: Create a Class Representing a Custom Security Token Service
How to: Create a Class Representing a Custom Binary Security Token