WSE 3.0, Kerberos & Windows Server 2003 (IIS 6.0)



WSE Community:

I'm wondering if anyone that has successfully implemented a Kerberos on IIS
6.0 using WSE 3.0 would be willing to post or direct me to a working Kerberos
Example using C#. I’ve been through the WSE 3.0 “Web Service Security”
Patterns & Practices guide. Also, I’ve been over the messaging Hands on lab.

So far I've successfully installed the “QuickStart” examples and got them
running on my Local Dev Box (Windows XP Pro SP2 & IIS 5.1), but I'm having
trouble getting an the examples up and running on our Testing server which is
a Windows Server 2003 in an Active Directory environment.

I've created a new user account, set the spn's for that account, created a
new application pool for my Service, added the useraccount to IIS_WPG,
enabled the account to act as system. I've installed the WSE 3.0 runtime and
restarted the machine. So on and so forth. (See my Code Below)

In order to get my code to work on my local machine I had to change the
Machine.config file and set the username to "system".
<system.web>
<processModel enable="true" userName="SYSTEM" password="AutoGenerate" />
...
</system.web>
Simply setting the ASP.NET account to "Act as part of the operating system"
under Local Security Settings > Local Policies > User Rights Assignments did
not work for me.


This is the code that I got working on my local machine.

I've divided up my test into 2 sections and I’ve included the source. If
someone could tell me why this doesn’t work on Windows Server 2003(IIS 6.0)
I’d be greateful!

------------------------------------------------------------------------------------------------
KERBEROS CLIENT FILES
http://localhost/kerberos/Client/

Site Configuration:
Directory Security: Integrated Windows Authentication
------------------------------------------------------------------------------------------------

//====================
//FileName: Default.aspx
//====================
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>

<html xmlns="http://www.w3.org/1999/xhtml"; >
<head runat="server">
<title>KerberosTest</title>
</head>
<body>
<form id="form" runat="server">
<b>User Is Authenticated: </b><span id="IsAuthenticated"
runat=server /> <br />
<b>User Authentication Type: </b><span id="AuthenticationType"
runat=server /> <br />
<b>ASP.NET UserName: </b><span id="ASPUser" runat=server /> <br />
<b>WebService UserName: </b><span id="WSUser" runat="server" />
</form>
</body>
</html>



//====================
//FileName: Default.aspx.cs
//====================
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.Services.Protocols;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Configuration;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3.Security;
using Microsoft.Web.Services3.Security.Tokens;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
AppBase client = null;
string username = "";
try
{
client = new AppBase();
username = client.CallService();
}
catch
{
//You will also throw an exception if you can't obtain the
token...
throw new SecurityFault(SecurityFault.FailedCheckMessage,
SecurityFault.FailedCheckCode);

}

IsAuthenticated.InnerHtml = User.Identity.IsAuthenticated.ToString();
AuthenticationType.InnerHtml =
User.Identity.AuthenticationType.ToString();
ASPUser.InnerHtml = User.Identity.Name.ToString();
WSUser.InnerHtml = username;

}
}


/// <summary>
/// This is a base class used by the various samples for
/// various configuration and commandline parsing needs.
/// </summary>
public class AppBase
{
SoapProtocolVersion _soapVersion = SoapProtocolVersion.Default;
public static string SubjectKeyIdentifierOID = "2.5.29.14";

protected SoapProtocolVersion SoapVersion
{
get
{
return _soapVersion;
}
}

public AppBase()
{
string soapVersion =
System.Configuration.ConfigurationManager.AppSettings["soapversion"];

switch (soapVersion)
{
case "soap11":
_soapVersion = SoapProtocolVersion.Soap11;
break;
case "soap12":
_soapVersion = SoapProtocolVersion.Soap12;
break;
default:
case "default":
_soapVersion = SoapProtocolVersion.Default;
break;
}
}

public string CallService()
{



string DNSName = System.Net.Dns.GetHostName();
KerberosToken kerbToken = new KerberosToken("host/" + DNSName +
"@MYDOMAIN",ImpersonationLevel.Identification);
if (kerbToken == null)
{
throw new ApplicationException("Unable to obtain security
token.");
}

// Create an instance of the Web service proxy
Service.ServiceWse serviceProxy = new Service.ServiceWse();
serviceProxy.PreAuthenticate = true;

// Configure the proxy
ConfigureProxy(serviceProxy);

// Set the ClientPolicy onto the proxy
serviceProxy.SetPolicy("ClientPolicy");

//string isCur = kerbToken.IsCurrent.ToString();
SoapContext RequestContext = serviceProxy.RequestSoapContext;
RequestContext.Security.Tokens.Add(kerbToken);
RequestContext.Security.Timestamp.TtlInSeconds = 300;

// Encrypt the SOAP body
//Now instruct the SOAP context to encrypt the transport with the
token credentials.
RequestContext.Security.Elements.Add(new EncryptedData(kerbToken));

// Call the service
string username = serviceProxy.getUserName();

return username + " ";
}


/// <summary>
/// Looks for any configuration settings that may modify
/// the Web service proxy used and modifies the proxy accordingly.
/// </summary>
protected void ConfigureProxy(SoapHttpClientProtocol protocol)
{
string remoteHost = ConfigurationManager.AppSettings["remoteHost"];
if (remoteHost != null)
{
Uri remoteHostUri = new Uri(remoteHost);
Uri protocolUrl = new Uri(protocol.Url);
Uri newUri = new Uri(remoteHostUri, protocolUrl.AbsolutePath);

if (protocol is Microsoft.Web.Services3.WebServicesClientProtocol)
{

((Microsoft.Web.Services3.WebServicesClientProtocol)protocol).Url =
newUri.AbsoluteUri;
}
else
{
protocol.Url = newUri.AbsoluteUri;
}
}

protocol.SoapVersion = SoapVersion;
}

}


//====================
//FileName: wse3policyCashe.config
//====================

<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy";>
<extensions>
<extension name="kerberosSecurity"
type="Microsoft.Web.Services3.Design.KerberosAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="kerberos"
type="Microsoft.Web.Services3.Design.KerberosTokenProvider,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="ClientPolicy">
<kerberosSecurity establishSecurityContext="false"
requireSignatureConfirmation="false"
messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="false"
ttlInSeconds="300">
<token>
<!-- By default this sample does not work until you have changed the
TargetMachineName value -->
<!-- Change the TargetMachineName value to the machine name with the
Web Service e.g. targetPrincipal="host/server1" -->


<kerberos targetPrincipal="host/MachineName"
impersonationLevel="Impersonation" />

</token>
<protection>
<request signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<response signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<fault signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="false" />
</protection>
</kerberosSecurity>
<requireActionHeader />
</policy>
</policies>



//====================
//FileName: web.config
//====================


<?xml version="1.0"?>
<configuration>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
</configSections>
<system.web>
<webServices>
<soapExtensionImporterTypes>
<add type="Microsoft.Web.Services3.Description.WseExtensionImporter,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
</soapExtensionImporterTypes>
</webServices>
<compilation debug="true">
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
<!---->
<authentication mode="Windows"/>
<identity impersonate="true"/>
<customErrors mode="Off"/>
</system.web>
<appSettings>
<add key="Service.Service"
value="http://localhost/Kerberos/Service/Service.asmx"/>
</appSettings>
<microsoft.web.services3>
<diagnostics>
<trace enabled="false" input="InputTrace.webinfo"
output="OutputTrace.webinfo"/>
<detailedErrors enabled="false"/>
</diagnostics>
<policy fileName="wse3policyCache.config"/>
</microsoft.web.services3>
</configuration>

------------------------------------------------------------------------------------------------
KERBEROS SERVICE FILES
http://localhost/kerberos/Service/


Site Configuration:
Anonymous Access: Checked
Directory Security: Integrated Windows Authentication

------------------------------------------------------------------------------------------------

//====================
//FileName: Service.cs
//====================
using System;
using System.IO;
using System.Diagnostics;
using System.Security.Principal;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3.Security.Tokens;

[WebService(Namespace = "http://localhost/Kerberos/Service";)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[Policy("ServerPolicy")]
public class Service : System.Web.Services.WebService
{
public Service () {

//Uncomment the following line if using designed components
//InitializeComponent();
}

[WebMethod]
public string getUserName() {

//
// Retrieve Client Kerberos Token
//
KerberosToken token =
RequestSoapContext.Current.Credentials.UltimateReceiver.GetClientToken<KerberosToken>();

return token.Principal.Identity.Name.ToString();
}

}


//====================
//FileName: web.config
//====================
<?xml version="1.0" encoding="utf-8"?>
<!--
Note: As an alternative to hand editing this file you can use the
web admin tool to configure settings for your application. Use
the Website->Asp.Net Configuration option in Visual Studio.
A full list of settings and comments can be found in
machine.config.comments usually located in
\Windows\Microsoft.Net\Framework\v2.x\Config
-->
<configuration>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
<appSettings />
<connectionStrings />
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="true">
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Windows" />
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.

<customErrors mode="RemoteOnly"
defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
<webServices>
<soapExtensionImporterTypes>
<add type="Microsoft.Web.Services3.Description.WseExtensionImporter,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
<soapServerProtocolFactory
type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</webServices>
</system.web>
<microsoft.web.services3>
<diagnostics>
<trace enabled="false" input="InputTrace.webinfo"
output="OutputTrace.webinfo" />
<detailedErrors enabled="false" />
</diagnostics>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>


//====================
//FileName: wse3policyCache.config
//====================
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy";>
<extensions>
<extension name="kerberosSecurity"
type="Microsoft.Web.Services3.Design.KerberosAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="ServerPolicy">
<authorization>
<allow role="Users" />
<deny role="*" />
</authorization>
<kerberosSecurity establishSecurityContext="false"
requireSignatureConfirmation="false"
messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="false"
ttlInSeconds="300">
<protection>
<request signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<response signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<fault signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="false" />
</protection>
</kerberosSecurity>
<requireActionHeader />
</policy>
</policies>


.



Relevant Pages

  • Re: pamkrbval: KDC policy rejects request for this entry
    ... If so can you do a kvno host/unix_client.domain.host.com and compare the number with the one in the keytab? ... Audit with a result code from the request of 0xC which from some ... The client libraries are based on MIT Kerberos V5 1.3.5 release. ... configuration guide I am following has a sample krb5.conf and only ...
    (comp.protocols.kerberos)
  • Re: Encryption Type wrong
    ... configured the KDC to use only that encryption type. ... If I use the default settings for Kerberos the behaviour is the same as above. ... Kerberos kadmind configuration. ...
    (comp.protocols.kerberos)
  • Re: Error while authenticating using mod_auth_kerb module
    ... received token seems to be NTLM, ... Kerberos module. ... I tried with IE as well as MOzilla browser. ... I followed the respective configuration for IE and Mozilla but still not ...
    (comp.protocols.kerberos)
  • Re: IIS integrated authentification file share permission problem
    ... How is the second name "test" configured in DNS? ... My experience with Kerberos is that when using DNS-based names, ... record name and build the SPN based on it. ... (In the network configuration I added the second adress to the adapter ...
    (microsoft.public.dotnet.framework.aspnet.security)

Quantcast