0

I'm trying to create a DLL file that I'll end up using in Excel VBA to download files from a SharePoint 2007 server. I'm running into issues with authentication as the download file only contains the html of the login page. Everyone accesses the site externally, however employees are not redirected to the login page, so somehow their Active Directory credentials are being passed.

You'll notice there are some message boxes in the code below, that's simple for debugging purposes so I know what is going on.

Being that I've spent well over two weeks just to get this far (I'm not an employee so I can't test this regularly) any help or guidance anyone here can provide would be greatly appreciated.

UPDATE: I should have clarified the variables that are being passed in.

If I paste the sptURL into a browser I get redirected to a login page, enter my credentials, and then I'm directed to the site once authenticated (I can see the authentication cookie passed in Fiddler). If an internal user pastes the URL into a browser they are taken to the site immediately (I'm assuming some sort of Active Directory authentication, although I can't confirm since I can't run any software like Fiddler on their system).

using System;
using System.Net;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;


namespace sptHELPER
{
    [ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
    public class sptDL
    {
        [DllExport("getResources", System.Runtime.InteropServices.CallingConvention.StdCall)]
        public static Int32 sptDownLoader(string sptURL, string sptItem, string sptDest, string sptUser = "", string sptPass = "")
        {
            System.Windows.Forms.MessageBox.Show("In function");
            int Result = 0;
            Result = 0;

            // create user credentials for SharePoint authentication 
            System.Net.NetworkCredential myCredentials = new System.Net.NetworkCredential();

            if (string.IsNullOrEmpty(sptUser))
            {
                myCredentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            }
            else
            {
                myCredentials.UserName = sptUser;
                myCredentials.Password = sptPass;
                myCredentials.Domain = "";
            }

            // set a temporary Uri to catch an invalid Uri later
            Uri mySiteSP = new Uri("http://www.defaultfallback");

            // create site string and download path string
            mySiteSP = new Uri(sptURL + "/" + sptItem);
            string dest = sptDest + "/" + sptItem;
            dest = dest.Replace("/", "\\");

            // create new WebClient with Cookies 
            WebClientWithCookies.CookieAwareWebClient mywebclient = new WebClientWithCookies.CookieAwareWebClient();
            mywebclient.Credentials = myCredentials;
            mywebclient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko");

            //download SharePoint file
            try
            {
                //mywebclient.UseDefaultCredentials = true;
                System.Windows.Forms.MessageBox.Show("Site: " + mySiteSP + Environment.NewLine + "Destination: " + dest);

                // download the file from SharePoint to the users computer
                mywebclient.DownloadFile(mySiteSP, dest);
            }
            catch (Exception ex)
            {
                Result = System.Runtime.InteropServices.Marshal.GetHRForException(ex);
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }

            return Result;

        }
    }   
}

// WebClient does not support cookies, so this extends the class to enable cookie support
namespace WebClientWithCookies
{
    public class CookieAwareWebClient : WebClient
    {
        public CookieContainer CookieContainer { get; set; }

        public CookieAwareWebClient()
          : base()
        {
            // messages for debugging purposes
            System.Windows.Forms.MessageBox.Show("Created a new cookie container");

            CookieContainer = new CookieContainer();
        }

        protected override WebRequest GetWebRequest(Uri address)
        {
            // messages for debugging purposes                
            System.Windows.Forms.MessageBox.Show("Entered cookie GetWebRequest");

            WebRequest request = base.GetWebRequest(address);

            HttpWebRequest webRequest = request as HttpWebRequest;
            if (webRequest != null)
            {
                webRequest.CookieContainer = CookieContainer;
                // messages for debugging purposes
                System.Windows.Forms.MessageBox.Show("added a cookie to the jar");
                System.Windows.Forms.MessageBox.Show(webRequest.ContentLength.ToString());
            }

            return request;
        }
    }
}
0

Your code looks correct (but still, I'm not sure the use of CookieAwareWebClient is needed in your case, WebClient should do the job).
So, maybe the problem is a simple one: are you 100% about the URL you pass to sptDownLoader?

If two kinds of users (external and internal) connect with different authentication mechanisms, they (most probably) use different URLs (two URLs actually mapped to the same SharePoint Web application, i.e. the same content, but with different authentication settings).
So, be sure to use the internal URL.

  • I've confirmed that the URL I'm passing is correct. Both internal and external users are accessing an external site. I've updated my post above regarding the specifics of each behavior when navigating to URL – pheeper Aug 16 '16 at 15:00
  • There's nothing in SP OOTB that makes the same URL authenticate via 2 different mechanisms, based on user "origin". So, either you have a custom login page that detects the internal users and does a redirection, or you have a reverse-proxy (RP) reached by your external users, and the RP does the FBA. We first need to clarify this point. When you access the site from the outside, does the login come from TMG (the reverse-proxy commonly used with SP), i.e. a screen like this i.stack.imgur.com/UUfW3.jpg? – Evariste Aug 16 '16 at 15:55
  • They have a custom login page, not a reverse-proxy – pheeper Aug 16 '16 at 16:03
  • OK, so we need to get what happens in that custom login page. 1. How do it detect a user is "internal" or "external"? 2. When an internal user lands on the custom login page, is he/she redirected to another Windows-authenticated page? How does the Windows-auth occur? – Evariste Aug 16 '16 at 16:21
  • if I had to guess (which is the best I have right now) I would say the internal users are being authenticated via Active Directory, similar to this example example: msdn.microsoft.com/en-us/library/ms180890(v=vs.80).aspx. – pheeper Aug 16 '16 at 23:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.