locked
Unauthorized 401 Exception Calling PSI Service using default credentials RRS feed

  • Question

  • Hi,

    I am trying to call "ReadStatusApprovalsSubmitted" in EPM 2010 and similar methods of statusing web service  in a custom webpart hosted in a page inside pwa by using default credentials as  tasks of currently logged in users are required.

     

    StatusingWebSvc.Statusing statusingSvc = new StatusingWebSvc.Statusing();
    statusingSvc.PreAuthenticate = true;
    statusingSvc.Credentials = System.Net.CredentialCache.DefaultCredentials;
    statusingSvc.Url = "http://sitename/pwa/_vti_bin/psi/statusing.asmx";
    statusingSvc.ReadStatusApprovalsSubmitted(false);

    This code results in 401 Unauthorized exceptions if i try to access the site from other machine other then server itself (Even if i access the site from other machine with System Account). When running the same code by impersonation with application pool account there is no error and records related to application pool account are shown.

    But i need to show the records related to currently logged in user and need to pass credentials of current user, so impersonation with AppPool Account is not an option.

    The same webpart is working fine on another environment when accessed from remote machine.

     


    Shabih
    • Edited by Shabih Ahmed Wednesday, October 19, 2011 5:01 PM
    Wednesday, October 19, 2011 5:00 PM

Answers

  • I figured out the problem. I had to run the code under elevated perveliges and to override the GetWebRequest method of Statusing and all other web services.

    class StatusingDerived : StatusingWebSvc.Statusing
        {
            private static String ContextString = String.Empty;
    
            protected override WebRequest GetWebRequest(Uri uri)
            {
                //here we are overriding the GetWebRequest method and adding the 2 web request headers
                WebRequest webRequest = base.GetWebRequest(uri);
    
                if (ContextString != String.Empty)
                {
                    webRequest.UseDefaultCredentials = true;
                    webRequest.Credentials = CredentialCache.DefaultNetworkCredentials;
                    webRequest.Headers.Add("PjAuth", ContextString);
                    webRequest.Headers.Add("ForwardFrom", "/_vti_bin/psi/statusing.asmx");
                    webRequest.PreAuthenticate = true;
                    webRequest.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
                }
    
                return webRequest;
            }
    
    
            public static void SetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid)
            {
                ContextString = GetImpersonationContext(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid);
            }
    
            private static String GetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid)
            {
                PSLibrary.PSContextInfo contextInfo = new PSLibrary.PSContextInfo(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid);
                String contextString = PSLibrary.PSContextInfo.SerializeToString(contextInfo);
                return contextString;
            }
        }
    



    Shabih
    • Marked as answer by Shabih Ahmed Sunday, October 23, 2011 5:38 AM
    Sunday, October 23, 2011 5:38 AM

All replies

  • Hi Guys,

    Does PSI Supports these requirements, or is it not possible ?


    Shabih
    Thursday, October 20, 2011 8:06 AM
  • I am facing the same prob, have you find any solution?

     

    Regards

    Thursday, October 20, 2011 11:10 AM
  • Hi Shabih,

    For the PSI, anonymous access is not supported, so the PreAuthenticate property has no effect. See http://msdn.microsoft.com/en-us/library/system.web.services.protocols.webclientprotocol.preauthenticate.aspx.

    ReadStatusApprovalsSubmitted gets submitted approvals only for the user who is logged on PWA, and returns a StatusApprovalDataSet.

    The SDK has a code sample in UpdateStatusApprovals that includes a call to ReadStatusApprovalsSubmitted.

    --Jim


    Jim Corbin [MSFT]
    Thursday, October 20, 2011 5:44 PM
  • I figured out the problem. I had to run the code under elevated perveliges and to override the GetWebRequest method of Statusing and all other web services.

    class StatusingDerived : StatusingWebSvc.Statusing
        {
            private static String ContextString = String.Empty;
    
            protected override WebRequest GetWebRequest(Uri uri)
            {
                //here we are overriding the GetWebRequest method and adding the 2 web request headers
                WebRequest webRequest = base.GetWebRequest(uri);
    
                if (ContextString != String.Empty)
                {
                    webRequest.UseDefaultCredentials = true;
                    webRequest.Credentials = CredentialCache.DefaultNetworkCredentials;
                    webRequest.Headers.Add("PjAuth", ContextString);
                    webRequest.Headers.Add("ForwardFrom", "/_vti_bin/psi/statusing.asmx");
                    webRequest.PreAuthenticate = true;
                    webRequest.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
                }
    
                return webRequest;
            }
    
    
            public static void SetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid)
            {
                ContextString = GetImpersonationContext(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid);
            }
    
            private static String GetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid)
            {
                PSLibrary.PSContextInfo contextInfo = new PSLibrary.PSContextInfo(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid);
                String contextString = PSLibrary.PSContextInfo.SerializeToString(contextInfo);
                return contextString;
            }
        }
    



    Shabih
    • Marked as answer by Shabih Ahmed Sunday, October 23, 2011 5:38 AM
    Sunday, October 23, 2011 5:38 AM