18 Replies Latest reply on Jan 20, 2011 7:45 PM by jlakumb

    IIS Windows Authentication - PI SDK

    mrai
      We have an asp.net application that uses the PI SDK to connect to PI. We are running into IIS (IIS7) double-hop (Windows Impersonation) issue when we deploy this application. We have our PI servers in one domain and the IIS servers in a different domain. We have established a trust between the domains and have enabled kerberos delegation. Even so, the PI SDK call to PI server is using the Process Account of IIS instead of the Windows Account of the logged in user. We know it's not a PI SDK issue  but have you encountered similar issue? If so, how did you solve this. We are stuck on this issue for a while and any help on this is much appreciated.  Also, what is your recommendation for using PI SDK calls in a web application? Thanks Biju
        • Re: IIS Windows Authentication - PI SDK
          dholareeyakt

          have you tried to impersonation when calling pisdk code and undo impersonation when it is done with specific user account?

           

          i think it should work. that specific user account should have access to pi in that different domain

           

           

           

           

          • Re: IIS Windows Authentication - PI SDK

            @Biju Vargheese: have you made any progress on this? As you accurately pointed out, this is not exactly a PI SDK issue, but rather an IIS/Windows Security one... however I do know there are some very knowledgeable people on the vCampus community, in the IIS/security space (Kireet seems to have experience with this ). So I'm thinking you might want to share some of your configuration settings (screenshots?) and let us try to help you...

             

            Biju Vargheese

            Also, what is your recommendation for using PI SDK calls in a web application?
            Per this other discussion thread and our "Optimizing PI SDK Applications" webinar, the PISDK.ServerManager object is the preferred approach. You might want to initiate a new discussion thread on this very topic, if you're looking for more specific assistance with this object.

              • Re: IIS Windows Authentication - PI SDK
                mrai

                Steve and Kireet, Thank you for following up on this. We resolved the PI SDK impersonation issue. The problem was calling STA COM library (PI SDK) fromthe ASP.NET (MTA Threads). According to Microsoft (http://support.microsoft.com/kb/325791) the impersonation token is not passed to the STA thread during the call. To solve this, we need to make the ASPX page run as an STA thread. This can be done by using the AspCompat="true" attribute in the page. This fixes the problem. However, running the page as STA thread affects performance. We still do have the cross domain kerberos delegation issue. Our team is working with Microsoft to resolve the same. For now, we have decided to use PI Users and map them to the business AD groups in our database. Thanks Biju

                  • Re: IIS Windows Authentication - PI SDK

                    Glad to read you found the root cause of the issue, and hopefully you can resolve this cross-domain Kerberos issue with Microsoft. And thanks for sharing this, I'm sure it will be useful to other people on the community as well...

                     

                    I'm not sure what you are doing with the PI SDK in your application, but you might want to look into other ways to get that PI System data, if you think you would benefit from a multi-threaded architecture (AF SDK, PI Web Services, PI OLEDB?).

                     

                    If you need further assistance with which product would suit your need better, please do not hesitate to initiate a new discussion thread (since this thread is specific to IIS Windows Authenticaiton), or contact us at vCampus@osisoft.com if this requires you to communicate things you would consider private.

                      • Re: IIS Windows Authentication - PI SDK
                        mrai

                        Steve,

                         

                        We have resolved the cross domain kerberos issue with the help of Microsoft. Now we are able to do windows authentication across domains.

                         

                        We ran into an interesting scenario when we were testing for windows authentication. This is not related to domains. We were using

                         

                        ServerManager get_Item() to get connections to the PI Server. This call succeeds in using Windows Authentication to get the connection the first time. Any subsequent calls to get_Item() fails with the error "No PI user was recorded for a trusted connection" (It is switching back to process account). However, if we get the Server from the PISDKClass.Servers table and call Open(""), it works everytime.

                          • Re: IIS Windows Authentication - PI SDK

                            Thanks for following up! Is there any information you can share with us, on how you addressed the cross-domain Windows authentication issue? Is that something you think we should add to our documentation?

                             

                            As for the behaviour you observed on ServerManager.get_Item(), I'll let the experts speak to this

                              • Re: IIS Windows Authentication - PI SDK
                                mrai

                                Steve,

                                 

                                This is a good KB article at tech support to get started: http://techsupport.osisoft.com/support+solution/7/kb00100.htm

                                 

                                It will be really helpful there is a document that addresses using PI SDK in an ASP.NET / IIS environment.

                                 

                                Here are the steps (Not necessary in order):

                                1. Configure the site's application pool to run with process account.
                                2. Create HTTP SPN's for the process account.
                                3. Setup unconstrained delegation for the process account in AD (“Trust this user for delegation to any service (Kerberos only)”).
                                4. If you are having your IIS server in one domain and the PI servers in another domain on a different forest, establish a one-way forest trust from the IIS domain to PI domain.
                                5. Make sure you use Fully Qualified Domain Names (PISERVER.domain), else Kerberos fails.
                                6. Enable windows authentication in IIS.
                                7. Make sure your client PC is running Windows XP SP3 or later.
                                8. Set AspCompat="true" attribute in the ASPX pages that make PI SDK calls (Forces it to run as STA thread).
                                9. Use Server.Open() instead of ServerManager.get_Item(). ServerManager.get_Item() seems to use the process account after the first call.
                              • Re: IIS Windows Authentication - PI SDK
                                ken

                                This is Ken Coates from the SDK Team.

                                 

                                When you connect to a server using Server Manager and Windows Authentication, the SDK is caching your Windows Principal Identity so it can reuse that and not have to authenticate you each time you make a call to the server.

                                 

                                If you subsequently make a ServerManager.get_Item call as a different identity, then you can see the error you list. So I suspect that the identity of the thread making the get_Item call was the process account rather than the Windows Principal identity that succeeded the first time.

                                 

                                You can use Windows calls to determine your identity. Perhaps you could insert some test code which would list your identity before each get_Item call in your scenario. Then we could determine what identity was being used in each case.

                                 

                                 

                                  • Re: IIS Windows Authentication - PI SDK
                                    mrai

                                    Ken,

                                     

                                    Thanks for looking into this. We are making the calls to ServerManager.get_Item as the same identity. In fact if you refresh the same page it fails the second time. Again, it works perfectly if we use Server.Open(). Is the ServerManager creating any threads?

                                      • Re: IIS Windows Authentication - PI SDK
                                        ken

                                        Biju,

                                         

                                        So you can make two ServerManager.get_item calls in a row from the same code and the second time it fails?

                                         

                                        Or is it only when you refresh the page?

                                         

                                         

                                          • Re: IIS Windows Authentication - PI SDK
                                            mrai

                                            Ken,

                                             

                                            I tried making two calls in a row and it works fine. It is failling only when we referesh the page.

                                              • Re: IIS Windows Authentication - PI SDK
                                                ken

                                                I think the next step would be to find out the Windows Principal Identity before making the ServerManager.get_Item call. Presumably it is different when the page is refreshed.

                                                 

                                                One way to do this is to call OpenThreadToken, GetTokenInformation (asking for TokenUser), which then returns a TOKEN_USER structure which contains a SID_AND_ATTRIBUTES structure that contains the SID.  Then you can call LookupAccountSid to get the actual principal name and domain.

                                                 

                                                Here is a website that shows the code:

                                                 

                                                http://nibuthomas.wordpress.com/2008/01/08/how-to-get-name-of-owner-of-a-process/

                                                 

                                                 

                                                  • Re: IIS Windows Authentication - PI SDK
                                                    mrai

                                                    Ken,

                                                     

                                                    ASPX page has the User.Identity property that gives the current Windows Principal Identity.

                                                     

                                                    string user = this.User.Identity.Name;

                                                     

                                                    This is always giving my windows identity no matter how many times I refresh. Also, I got some code to get the current process owner.

                                                    string ProcessOwner = ""; 

                                                    ObjectQuery x = new ObjectQuery("Select * From Win32_Process where ProcessID ='" + Process.GetCurrentProcess().Id + "'"); ManagementObjectSearcher mos = new ManagementObjectSearcher(x);

                                                    foreach (ManagementObject mo in mos.Get())

                                                        string[] s = new string[2]; mo.InvokeMethod("GetOwner", (object[])s); 
                                                        ProcessOwner = s[0].ToString(); break;
                                                    }

                                                    This is always giving as ASPNET.

                                                     

                                                    We are storing the ServerManager as an application object (HttpApplicationState). So for the next call we get the ServerManager from the HttpApplicationState. Instead of that, I tried creating ServerManager for every call and it works everytime. Is it related to the thread where the ServerManager is created?

                                                      • Re: IIS Windows Authentication - PI SDK
                                                        ken

                                                        Here is a a theory about what is going on here and how to do it right.  Most likely multiple threads are involved. The ServerManager is created on one thread but the automatic IIS impersonation is happening on a different thread and the calls to ServerManager from that thread are being marshaled by COM (STA) to the thread where the ServerManager was created and where the thread identity is not the impersonated identity. 

                                                         

                                                         

                                                         

                                                        Here's one way that should work.  The web application should create a thread it is going to use for SDK work and create its ServerManager in that thread.  When it receives a call from IIS it should grab the identity of the thread where it receives the call, (typically IIS is impersonating the caller at that point), and pass it to the SDK thread and impersonate that identity.  Now the ServerManager lives on the thread where the impersonation is being done so when Item is called it will use that principal to get the proper session context. 

                                                         

                                                         

                                                         

                                                        While creating a ServerManager each time IIS calls the web app would work, this is very expensive and slow. 

                                                         

                                                         

                                                         

                                                        There is a web services example on the support site that does .Net impersonation that might be helpful. It uses ServerManager. I would have pointed you at this earlier, but I just found out about it. 

                                                         

                                                         

                                                         

                                                        http://techsupport.osisoft.com/techsupport/nontemplates/Download%20Center/DownloadCenter.aspx?Download_content=Sample+Code+-+.NET&download_product=04FEBF74-2D69-4CA8-8DCE-7878E6337D3F

                                                         

                                                         

                                                         

                                                        The process identity is never going to be the right approach as that won't change throughout the life of the web application.  Impersonation always happens on a thread.

                                                         

                                                         

                                                         

                                                        While creating a ServerManager each time IIS calls the web app would work, this is very expensive and slow. 

                                                         

                                                          • Re: IIS Windows Authentication - PI SDK
                                                            mrai
                                                            Ken,

                                                            Thank you for following up on this. We did try the example web service and it works good. However, we have a few questions.

                                                            1. Do we just create just one SDK Thread for the whole application? If so, is it scalable?
                                                            2. The SDK Thread is using Windows Forms for the delegation. Is it OK to use the Windows Forms library in a web environment?

                                                              • Re: IIS Windows Authentication - PI SDK
                                                                ken

                                                                Biju Vargheese

                                                                Ken,

                                                                Thank you for following up on this. We did try the example web service and it works good. However, we have a few questions.

                                                                1. Do we just create just one SDK Thread for the whole application? If so, is it scalable?
                                                                2. The SDK Thread is using Windows Forms for the delegation. Is it OK to use the Windows Forms library in a web environment?

                                                                 

                                                                Biju,

                                                                 

                                                                1) You are correct that using a single thread could have scaling problems. Our suggestion is that you create an STA thread pool if you have scaling problems. NOTE: You can't use a standard .NET thread pool since that has to use MTA threads and can't be changed to use STA threads.

                                                                 

                                                                2) I don't have an opinion on this question. I have minimal experience writing web applications.