Gemini Community Support Site

This Gemini community support site can be used to find solutions to product issues. You can log in using Open Id, Google Profile and even Facebook. Feel free to ask a question or browse FAQs and documentation. Product tour videos are also available along with how-to videos demonstrating key Gemini capabilities.




'--' is an unexpected token. The expected token is '>'. Line 81, position 5.

web-app

I am having trouble with the Gemini ReST services.  Here is my current environment:

Gemini Version: v3.6.0 Beta 2 Build 2526

CounterSoft.Gemini.Commons.dll Version: 3.6.0.2526

CounterSoft.Gemini.WebServices.dll Version: 3.6.0.2526

 

Background:  I will be using Gemini as a central repository for issues within my company.  I need to interface an existing ASP.NET 2.0 web application to send and receive information to/from Gemini.

1.      I have configured Gemini to use Windows authentication.  Working great.

2.      The ASP.NET 2.0 web application is an Intranet application that uses Windows authentication.  Working great.

3.      Both Gemini and the web application reside on a Windows 2003 server running IIS 6.

4.      The web application uses an Application Pool who’s Identity is set to Network Service

Problem: When the ASP.NET 2.0 web application calls for information from Gemini via the ServiceManager object, the credentials of the application pool are being sent to Gemini for authentication instead of the logged in users credentials.  Here is a code snippet of the offending routine:

<code>

ServiceManager serviceManager = new ServiceManager(Properties.Settings.Default.GemniURL, Request.LogonUserIdentity.Name, "", "", true);

UserEN user = serviceManager.UsersService.WhoAmI();

</code>

The behavior I was assuming was, if I set the windowsAuthentication parameter to true, and provided the user’s domain log in name in the username parameter, that the ServiceManager object would authenticate the user specified in the username parameter.  What is happening is the Application Pool’s Identity is being passed to Gemini, regardless of the username parameter.

So, to override the Application Pool’s Identity to be used, in the ASP.NET 2.0 web application’s web.config file, I added to the <system.web> config section:

<code>

<identity impersonate="true" />

</code>

Thus, IIS is impersonating the logged in user and not use the Application Pool’s identity.  When testing this configuration, I received the following exception:

System.Xml.XmlException was caught

  Message="'--' is an unexpected token. The expected token is '>'. Line 81, position 5."

  Source="System.Xml"

  LineNumber=81

  LinePosition=5

  SourceUri="http://www.w3.org/TR/html4/strict.dtd"

  StackTrace:

       at System.Xml.XmlTextReaderImpl.Throw(Exception e)

       at System.Xml.XmlTextReaderImpl.DtdParserProxy.System.Xml.IDtdParserAdapter.Throw(Exception e)

       at System.Xml.DtdParser.Throw(Int32 curPos, String res, String[] args)

       at System.Xml.DtdParser.ThrowUnexpectedToken(Int32 pos, String expectedToken1, String expectedToken2)

       at System.Xml.DtdParser.ScanClosingTag()

       at System.Xml.DtdParser.GetToken(Boolean needWhiteSpace)

       at System.Xml.DtdParser.ParseEntityDecl()

       at System.Xml.DtdParser.ParseSubset()

       at System.Xml.DtdParser.ParseExternalSubset()

       at System.Xml.DtdParser.ParseInDocumentDtd(Boolean saveInternalSubset)

       at System.Xml.DtdParser.Parse(Boolean saveInternalSubset)

       at System.Xml.XmlTextReaderImpl.DtdParserProxy.Parse(Boolean saveInternalSubset)

       at System.Xml.XmlTextReaderImpl.ParseDoctypeDecl()

       at System.Xml.XmlTextReaderImpl.ParseDocumentContent()

       at System.Xml.XmlTextReaderImpl.Read()

       at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)

       at System.Xml.XmlDocument.Load(XmlReader reader)

       at System.Xml.XmlDocument.Load(Stream inStream)

       at CounterSoft.Gemini.Commons.Rest.Serializer.ConvertToObject[T](Stream stream)

       at CounterSoft.Gemini.WebServices.BaseService.GetObjectFromReponse[T](Stream stream)

       at CounterSoft.Gemini.WebServices.BaseService.ThrowResponseException(WebResponse response)

       at CounterSoft.Gemini.WebServices.BaseService.ProcessResponse[T](String url, Object obj, RequestType requestType)

       at CounterSoft.Gemini.WebServices.BaseService.GetResponse[T](String url, Object o, RequestType r)

       at CounterSoft.Gemini.WebServices.BaseService.WhoAmI()

       at IssueTrackerPOC.GeminiAPI.Page_Load(Object sender, EventArgs e) in <<Snip for security purposes>>\GeminiAPI.aspx.cs:line 32

 

Please advise soonest if you can or cannot replicate this and if replicable, what the fix/patch is.

Also, do you have any recommendations for tools that can be used to interrogate the Xml being passed to and from the ReST service?

dongertz
· 1
dongertz
Replies (12)
helpful
0
not helpful

Tested with 3.6 and works as expected. You are doing the right thing (impersonate) as we can't trust the username sent via the service manager for authentication.
Please make sure that in IIS you don't have anomnymous access enabled for the Gemini site.


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

Thanks for the quick reply.  I have verified that Anonymous access IS NOT enabled, but I'm still receiving the error.  How did you test that it worked on your side?  Can you send me your test harness or code snippet of the successful test, so that, I can try it on my side?


dongertz
· 1
dongertz
helpful
0
not helpful

I ran the same code as you, created a service manager and called WhoAmI()....

Try and call the service directly without the service manager to see what is that you are getting back. It seems like you are being sent back a page and not XML.


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

How did you configure the application pool?  Are you using the Network Service account?  I am new to using REST.... do you have a sample piece of code to "call the service directly"?  Any help is appreciated.


dongertz
· 1
dongertz
helpful
0
not helpful

Here is a sample code:

HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://localhost/gemini/api/users.ashx/users/username/" + HttpUtility.UrlEncode("manager"));
            req.Method = "GET";
            req.Accept = "text/xml";
            req.ContentType = "text/xml";
            HttpWebResponse res = req.GetResponse() as HttpWebResponse;
            string responseString;
            using (StreamReader sr = new StreamReader(res.GetResponseStream()))
            {
                responseString = sr.ReadToEnd();
            }


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

Thanks for the sample.  When I execute the code, on the req.GetResponse call, a "The remote server returned an error: (401) Unauthorized." System.Net.WebException is being returned.

1.  Gemini is configured to use Windows authenication.  Is there any special permission that need to be set on the api directory?

2.  The .NET 2.0 web app that I used to call the sample code also used Windows authentication and <identity impersonate="true" /> is set in the web.config file.

3.  The URL I'm referencing in the HttpWebRequest.Create is:

http://<<url to gemini>>/api/users.ashx/users/username/<<DOMAIN NAME>>/<<DOMAIN Username>>

4.  I'm using my credentials to access the .NET 2.0 web app and I am a Domain Admin and a Gemini Administrator.

Also, in the Gemini SystemLog, the following Error is being recorded:

The file '/rss/Issues.ashx' does not exist. at System.Web.UI.Util.CheckVirtualFileExists(VirtualPath virtualPath) at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile) at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile) at System.Web.Compilation.BuildManager.GetVPathBuildResult(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile) at System.Web.UI.SimpleHandlerFactory.System.Web.IHttpHandlerFactory2.GetHandler(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) at System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig) at System.Web.HttpApplication.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

 

Sorry that something so simple is taking so long to resolve and I appreciate your time to help me resolve this.

Cheers.

 


dongertz
· 1
dongertz
helpful
0
not helpful

You need to encode the username:

HttpUtility.UrlEncode("DOMAIN\USER"));

Also, set the credentials on the request.


Saar Cohen
· 5000
Saar Cohen
helpful
0
not helpful

For your tests, are the Gemini ASHX files and your test application being run on the same machine or is the web app on one server and Gemini installed on another?

If the web app and Gemini are installed on the same machine, can you install your web app on another machine and re-run your test?  I've be doing some research and I think the problem is being caused by the dreaded "double-hop" authenication issue when using Windows authenication.


dongertz
· 1
dongertz
helpful
0
not helpful

The test was run between a client and a server (2 machines).
What is the page you are getting back?


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

The page being returned is a 401 - Unauthorized error.  It appears that eventhough I have setup IIS to use Integrated Windows Authenciation, set the web.config's authenication mode to Windows and identity impersonate to true, the logged in users credentials were not being passed.  It appears to be a "double-hop" authenication issue and that the user is being authenticated using NTLM instead of Kerberos.

I have "fixed" the problem with the following steps:

  1. Created a domain user account to run the application pool as.
  2. Ensured the Active Directory domain's functional level was set to Windows Server 2003.  This is for kerberos delegation.
  3. Set the web site for the .Net application in IIS to use Integrated Windows Authenication.
  4. Configure the App Pool for the .Net application to use the domain user and associate App Pool with IIS web site.
  5. Set the .Net application's web.config file's authenication mode to Windows and identity impersonate to true.
  6. Used adsutil.vbs to check to make sure the .Net application's web site NTAuthenicationProviders were configured to use both Negotiate and NTLM.  Note: If Negotiate is not set, Kerberos will not work.
  7. Used setspn.exe to configured the Service Prinicpal Name (SPN) for the .Net application web site and bound it to the user account of the App Pool.  See http://technet.microsoft.com/en-us/library/cc773257(WS.10).aspx
  8. Within Active Directory, permitted the domain user Delegation Trust.
  9. Configure the App Pool for Gemini to use the domain user and associate App Pool with the Gemini IIS web site.
  10. Used adsutil.vbs to check to make sure the Gemini web site NTAuthenicationProviders were configured to use both Negotiate and NTLM.  Note: If Negotiate is not set, Kerberos will not work.
  11. Used setspn.exe to configured the Service Prinicpal Name (SPN) for the Gemini web site and bound it to the user account of the App Pool

In my case, the above 11 steps were needs to ensure Kerberos authenication from the .Net web application through to the Gemini API REST services.  Now, when the user accesses the .Net web application, the user's credentials are being passed to the Gemini API REST service and the "double-hop" authenication problem has gone away.

One big note !!!  Both the .Net web application and Gemini web site are being used and accessed from our corporate Intranet.  The above 11 steps work for us (ie: my company) and are not any recommendation of best practices and we take no responsibility and assume no liability.

   

 

 


dongertz
· 1
dongertz
helpful
0
not helpful

Many thanks for the update. Glad you managed to get it workling.


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

I am using Windows 2003 IIS 6.0 x86, Forms Authentication. This article fixed this issue for me: link text


Brett
· 1
Brett