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 Microsoft.Web.Services3.Security.Tokens.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.Services3.Addressing Imports Microsoft.Web.Services3.Design Imports Microsoft.Web.Services3.Security Imports Microsoft.Web.Services3.Security.Cryptography Imports Microsoft.Web.Services3.Security.Tokens Imports Microsoft.Web.Services3.Security.Utility
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.Services3.Addressing; using Microsoft.Web.Services3.Design; using Microsoft.Web.Services3.Security; using Microsoft.Web.Services3.Security.Cryptography; using Microsoft.Web.Services3.Security.Tokens; using Microsoft.Web.Services3.Security.Utility;
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 String Get Return XmlTokenNames.TypeNames.TokenType End Get End Property
public override string TokenType { get { return XmlTokenNames.TypeNames.TokenType; } }
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.
' The LoadTokenFromXml method deserializes an XML element into ' a security token. Public Overrides Function LoadTokenFromXml(ByVal element As XmlElement) As SecurityToken Return New XmlToken(element) End Function
// The LoadTokenFromXml method deserializes an XML element into // a security token. 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.
' 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 = _ XmlTokenNames.TypeNames.TokenType)) 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 XmlToken = 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 ' If execution reaches here, the custom XML ' security token could not be loaded. Return Nothing End Function
// 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 == XmlTokenNames.TypeNames.TokenType)) { // 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.
' 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
// 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."); } }
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.Services3.Addressing
Imports Microsoft.Web.Services3.Design
Imports Microsoft.Web.Services3.Security
Imports Microsoft.Web.Services3.Security.Cryptography
Imports Microsoft.Web.Services3.Security.Tokens
Imports Microsoft.Web.Services3.Security.Utility
Namespace CustomXmlSecToken
Public Class XmlTokenManager : Inherits Microsoft.Web.Services3.Security.Tokens.SecurityTokenManager
Public Overrides ReadOnly Property TokenType() As String
Get
Return XmlTokenNames.TypeNames.TokenType
End Get
End Property
' The LoadTokenFromXml method deserializes an XML element into
' a security token.
Public Overrides Function LoadTokenFromXml(ByVal 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 = _
XmlTokenNames.TypeNames.TokenType)) 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 XmlToken = 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
' 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.Services3.Addressing;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3.Security;
using Microsoft.Web.Services3.Security.Cryptography;
using Microsoft.Web.Services3.Security.Tokens;
using Microsoft.Web.Services3.Security.Utility;
namespace CustomXmlSecToken
{
public class XmlTokenManager : SecurityTokenManager
{
public override string TokenType
{
get
{
return XmlTokenNames.TypeNames.TokenType;
}
}
// 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 ==
XmlTokenNames.TypeNames.TokenType))
{
// 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 Binary Security Token