How to: Impersonate the Credentials Associated with a KerberosToken
WSE enables you to impersonate the credentials associated with a KerberosToken security token in a SOAP message when a SOAP message sender allows it. A SOAP message sender specifies that the credentials associated with the security token can be impersonated by setting a property in code or adding a claim to send side policy. Once impersonation is enabled by the SOAP message sender, a recipient can impersonate the credentials using code.
To impersonate the credentials associated with a KerberosToken security token in a SOAP message to access a constrained set of resources on a remote computer (constrained delegation), additional configuration steps are required. For more details, see How to: Configure an Application to Use Constrained Delegation.
The following procedures detail how to use policy or code to specify that a KerberosToken security token can be impersonated and how a SOAP message receiver of the KerberosToken security token uses to code to impersonate the credentials associated with it.
Whether you use code, WSE must be enabled to process the incoming SOAP messages.
To use code to specify that a recipient of a KerberosToken can impersonate the credentials associated with a KerberosToken
Open the Web service client project in Visual Studio 2005.
Add references to the Microsoft.Web.Services3 and System.Web.Services assemblies.
- On the Project menu, click Add Reference.
- On the .NET tab, select the component named Microsoft.Web.Services3.dll, and then click Select.
- On the .NET tab, select the component named System.Web.Services.dll, and then click Select.
- Click OK.
Add a Web Reference to the Web service that is to receive the SOAP message containing a KerberosToken security token.
- On the Project menu, click Add Web Reference.
- In the Add Web Reference dialog box, type the URL for the Web service in the Address box, and then click Go.
- Verify that the items in the Available references box are the items you want to reference in your project, and then click Add Reference.
Edit the proxy class to derive from WebServicesClientProtocol.
In Solution Explorer, right-click the Reference.cs file for the recently added Web reference, and then click View Code.
Note
If the Reference.cs file that contains the proxy class is not visible, click the Show All Files icon in Solution Explorer, and then expand the Reference.map node.
Change the base class of the proxy class to Microsoft.Web.Services3.WebServicesClientProtocol.
This modifies the proxy class to emit routing and security SOAP headers when communicating with the Web service. The following code example modifies a proxy class namedService1
to derive from Microsoft.Web.Services3.WebServicesClientProtocol.Public Class Service1 Inherits Microsoft.Web.Services3.WebServicesClientProtocol
public class Service1 : Microsoft.Web.Services3.WebServicesClientProtocol
Note
If you select Update Web Reference in Visual Studio .NET 2003, the proxy class is regenerated, the base class is reset to SoapHttpClientProtocol, and you must change the class the proxy class derives from again.
Add the following using directives to the top of the file containing the Web service client code:
Imports System Imports System.Windows.Forms Imports Microsoft.Web.Services3 Imports Microsoft.Web.Services3.Security Imports Microsoft.Web.Services3.Security.Tokens
using System; using System.Windows.Forms; using Microsoft.Web.Services3; using Microsoft.Web.Services3.Security; using Microsoft.Web.Services3.Security.Tokens;
Edit the method that communicates with the Web service to add the security credentials to the SOAP message.
Add code to create a KerberosToken security token that can be impersonated.
Use a constructor that takes an ImpersonationLevel and for that parameter specify ImpersonationLevel.Impersonation.
The following code example creates an instance of the KerberosToken class and specifies that it can be used for impersonation. Thehostname
variable is the name of the computer hosting the target Web service, and thednsDomainName
variable is the Kerberos realm that the host is a member of. The Kerberos realm is needed only when the SOAP message sender resides in a different domain or realm from the target Web service.Dim kerbToken As KerberosToken = _ New KerberosToken("host/" + hostname & _ "@" & domainName, ImpersonationLevel.Impersonation)
KerberosToken kerbToken = new KerberosToken( "host/" + hostname + "@" + domainName, ImpersonationLevel.Impersonation);
Get the SoapContext for the SOAP request that is being made to the Web service.
Service1
is the name of a proxy class for the Web service in the following code example.' Creates an instance of the Web service proxy. Dim serviceProxy As New AddNumbers ' Gets the SoapContext associated with the SOAP request. Dim requestContext As SoapContext = _ serviceProxy.RequestSoapContext
// Creates an instance of the Web service proxy. AddNumbers serviceProxy = new AddNumbers(); // Gets the SoapContext associated with the SOAP request. SoapContext requestContext = serviceProxy.RequestSoapContext;
Add the SecurityToken to the WS-Security SOAP header.
' Adds the token to the SOAP header. requestContext.Security.Tokens.Add(kerbToken)
// Adds the token to the SOAP header. requestContext.Security.Tokens.Add(kerbToken);
Specify the time-to-live (TTL) for the SOAP message to diminish the chance of someone intercepting the message and replaying it. The following code example sets the TTL to one minute.
' Sets the TTL to one minute. requestContext.Security.Timestamp.TtlInSeconds = 60
// Sets the TTL to one minute. requestContext.Security.Timestamp.TtlInSeconds = 60;
Call the Web service.
' Calls the Web service. Dim sum As Integer = serviceProxy.AddInt(a, b)
// Calls the Web service. int sum = serviceProxy.AddInt(a, b);
To use code to impersonate the credentials associated with a KerberosToken
Add code to the Web service method to obtain the KerberosToken security whose credentials you want to impersonate.
A SOAP message can contain multiple security tokens, which might sign or encrypt different portions of the SOAP message. Therefore, it is up to the application to determine which security token is impersonated.
The following code example defines and then calls a
GetBodySigningToken
method that obtains the KerberosToken security token that signed the <Body> element of the SOAP request.Public Function GetBodySigningToken(ByVal requestContext As SoapContext) As KerberosToken Dim token As KerberosToken = Nothing Dim securityElement As ISecurityElement For Each securityElement In requestContext.Security.Elements If (TypeOf securityElement Is MessageSignature) Then Dim sig As MessageSignature = _ CType(securityElement, MessageSignature) If ((sig.SignatureOptions And _ SignatureOptions.IncludeSoapBody) <> SignatureOptions.IncludeSoapBody) Then Dim sigToken As SecurityToken = sig.SigningToken If (TypeOf sigToken Is KerberosToken) Then token = CType(sigToken, KerberosToken) End If End If End If Next Return token End Function ... ' Get the KerberosToken security token that was used to sign the SOAP ' request. Dim kerbToken As KerberosToken = GetBodySigningToken(requestContext)
public KerberosToken GetBodySigningToken(SoapContext requestContext) { KerberosToken token = null; foreach (ISecurityElement securityElement in requestContext.Security.Elements) { if (securityElement is MessageSignature) { MessageSignature sig = (MessageSignature)securityElement; if ((sig.SignatureOptions & SignatureOptions.IncludeSoapBody) != SignatureOptions.IncludeSoapBody) { SecurityToken sigToken = sig.SigningToken; if (sigToken is KerberosToken) token = (KerberosToken)sigToken; } } } return token; } ... // Get the KerberosToken security token that was used to sign the SOAP // request. KerberosToken kerbToken = GetBodySigningToken(requestContext);
Ensure that the SOAP message sender specified that the KerberosToken security token can be used for impersonation.
The following code example ensures that a KerberosToken security token can be used for impersonation.
If kerbToken.ImpersonationLevel = ImpersonationLevel.Impersonation Then
if (kerbToken.ImpersonationLevel == ImpersonationLevel.Impersonation)
Get the Windows identity associated with the KerberosToken.
The following code example gets the Windows identity associated with the KerberosToken security token.
Dim identity As WindowsIdentity = _ CType(kerbToken.Principal.Identity, WindowsIdentity)
WindowsIdentity identity = kerbToken.Principal.Identity as WindowsIdentity;
Create a WindowsImpersonationContext object by impersonating the Windows identity.
The following code example creates a WindowsImpersonationContext object by impersonating the Windows identity.
Dim context As WindowsImpersonationContext = Nothing Try context = identity.Impersonate()
WindowsImpersonationContext context = null; try { context = identity.Impersonate();
Do the action required by your application that requires the Windows credentials associated with the KerberosToken security token.
The following code example opens a file on the Web service's computer using the credentials associated with the KerberosToken security token.
Dim stream As FileStream = File.Open("C:\Temp\test.txt", _ FileMode.Open, FileAccess.Read, FileShare.None) stream.Close()
FileStream stream = File.Open(@"C:\Temp\test.txt", FileMode.Open, FileAccess.Read, FileShare.None); stream.Close();
Stop impersonating the credentials associated with the KerberosToken security token.
The following code example stops impersonating the credentials associated with the KerberosToken security token.
context.Undo()
if (context != null) context.Undo();
Example
The following code example demonstrates how to impersonate the credentials associated with a KerberosToken security token.
Imports System
Imports System.IO
Imports System.Security.Principal
Imports System.Web.Services
Imports Microsoft.Web.Services3
Imports Microsoft.Web.Services3.Security
Imports Microsoft.Web.Services3.Security.Tokens
Namespace KerbImpersonate
<WebService(Namespace:="http://www.cohowinery.com/webservices/")> _
Public Class Service1
<WebMethod()> _
Public Function SayHello() As String
' Ensure that the request is a SOAP request.
Dim requestContext As SoapContext = RequestSoapContext.Current
If requestContext Is Nothing Then
Throw New ApplicationException("Only SOAP requests are permitted.")
End If
' Get the KerberosToken security token that was used to sign the SOAP
' request.
Dim kerbToken As KerberosToken = GetBodySigningToken(requestContext)
If kerbToken.ImpersonationLevel = ImpersonationLevel.Impersonation Then
' Get the Windows identity associated with the KerberosToken.
Dim identity As WindowsIdentity = _
CType(kerbToken.Principal.Identity, WindowsIdentity)
' Create a WindowsImpersonationContext object by impersonating
' the Windows identity.
Dim context As WindowsImpersonationContext = Nothing
Try
context = identity.Impersonate()
' Access the file on the local computer using the token's
' identity.
Dim stream As FileStream = File.Open("C:\Temp\test.txt", _
FileMode.Open, FileAccess.Read, FileShare.None)
stream.Close()
Finally ' Stop impersonating the credentials associated with the KerberosToken.
If Not context Is Nothing Then
context.Undo()
End If
End Try
End If
Return "Hello World"
End Function
Public Function GetBodySigningToken(ByVal requestContext As SoapContext) As KerberosToken
Dim token As KerberosToken = Nothing
Dim securityElement As ISecurityElement
For Each securityElement In requestContext.Security.Elements
If (TypeOf securityElement Is MessageSignature) Then
Dim sig As MessageSignature = _
CType(securityElement, MessageSignature)
If ((sig.SignatureOptions And _
SignatureOptions.IncludeSoapBody) <> SignatureOptions.IncludeSoapBody) Then
Dim sigToken As SecurityToken = sig.SigningToken
If (TypeOf sigToken Is KerberosToken) Then
token = CType(sigToken, KerberosToken)
End If
End If
End If
Next
Return token
End Function
End Class
End Namespace
using System;
using System.IO;
using System.Security.Principal;
using System.Web.Services;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Security;
using Microsoft.Web.Services3.Security.Tokens;
namespace KerbImpersonate
{
[WebService(Namespace="http://www.cohowinery.com/webservices/")]
public class Service1
{
[WebMethod]
public string SayHello()
{
// Ensure that the request is a SOAP request.
SoapContext requestContext = RequestSoapContext.Current;
if (requestContext == null)
throw new ApplicationException("Only SOAP requests are permitted.");
// Get the KerberosToken security token that was used to sign the SOAP
// request.
KerberosToken kerbToken = GetBodySigningToken(requestContext);
if (kerbToken.ImpersonationLevel == ImpersonationLevel.Impersonation)
{
// Get the Windows identity associated with the KerberosToken.
WindowsIdentity identity = kerbToken.Principal.Identity as WindowsIdentity;
// Create a WindowsImpersonationContext object by impersonating
// the Windows identity.
WindowsImpersonationContext context = null;
try
{
context = identity.Impersonate();
// Access the file on the local computer using the token's
// identity.
FileStream stream = File.Open(@"C:\Temp\test.txt", FileMode.Open,
FileAccess.Read, FileShare.None);
stream.Close();
}
finally
{
// Stop impersonating the credentials associated with the KerberosToken.
if (context != null)
context.Undo();
}
}
return "Hello World";
}
public KerberosToken GetBodySigningToken(SoapContext requestContext)
{
KerberosToken token = null;
foreach (ISecurityElement securityElement in
requestContext.Security.Elements)
{
if (securityElement is MessageSignature)
{
MessageSignature sig =
(MessageSignature)securityElement;
if ((sig.SignatureOptions &
SignatureOptions.IncludeSoapBody) != SignatureOptions.IncludeSoapBody)
{
SecurityToken sigToken = sig.SigningToken;
if (sigToken is KerberosToken)
token = (KerberosToken)sigToken;
}
}
}
return token;
}
}
}
See Also
Tasks
How to: Configure an Application to Use Constrained Delegation
Reference
Other Resources
Kerberos Ticket
Brokered Authentication – Kerberos
Kerberos Technical Supplement for Windows
Protocol transition & constrained delegation