Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Proxy PAC with EWS API

I have a web application that calls the EWS Managed API to connect to office365.

I've followed the Get started with EWS Managed API 2.0 client applications documentation on MSDN.

In the web.config I've specified the proxy pac:

<configuration>
  <system.net>
    <defaultProxy useDefaultCredentials="false">
      <proxy autoDetect="False" bypassonlocal="True" scriptLocation="http://example.com:8080/proxy.pac" usesystemdefault="False" />
    </defaultProxy>
  </system.net>
  [...]
</configuration>

And I try to connect to Exchange in the following way:

public static ExchangeService getExchangeService(String username)
{
    ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;

    ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
    service.Credentials = new WebCredentials(USER_365, PWD_365, DOMAIN_365);
    service.UseDefaultCredentials = true;

    //I've tried both WebProxy settings, this:
    service.WebProxy = WebRequest.GetSystemWebProxy();
    //And this (with no success):
    //service.WebProxy = WebRequest.DefaultWebProxy;

    //I've also tried Autodiscover...
    service.AutodiscoverUrl(USER_365, RedirectionUrlValidationCallback);
    //...and direct url
    //service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");

    service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, username);

    return service;
}

And the following are the method copied & pasted from MSDN:

private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
    // The default for the validation callback is to reject the URL.
    bool result = false;

    Uri redirectionUri = new Uri(redirectionUrl);

    // Validate the contents of the redirection URL. In this simple validation
    // callback, the redirection URL is considered valid if it is using HTTPS
    // to encrypt the authentication credentials. 
    if (redirectionUri.Scheme == "https")
    {
        result = true;
    }
    return result;
}

private static bool CertificateValidationCallBack(object sender,
    System.Security.Cryptography.X509Certificates.X509Certificate certificate,
    System.Security.Cryptography.X509Certificates.X509Chain chain,
    System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
    // If the certificate is a valid, signed certificate, return true.
    if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
    {
        return true;
    }

    // If there are errors in the certificate chain, look at each error to determine the cause.
    if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
    {
        if (chain != null && chain.ChainStatus != null)
        {
            foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
            {
                if ((certificate.Subject == certificate.Issuer) &&
                   (status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
                {
                    // Self-signed certificates with an untrusted root are valid. 
                    continue;
                }
                else
                {
                    if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
                    {
                        // If there are any other errors in the certificate chain, the certificate is invalid,
                        // so the method returns false.
                        return false;
                    }
                }
            }
        }

        // When processing reaches this line, the only errors in the certificate chain are 
        // untrusted root errors for self-signed certificates. These certificates are valid
        // for default Exchange server installations, so return true.
        return true;
    }
    else
    {
        // In all other cases, return false.
        return false;
    }
}

I tried to comment out the line:

//service.Url = new Uri("https://outlook.office365.com/ews/Exchange.asmx");

And add the Autodiscover:

service.AutodiscoverUrl(username);

Set the proxy or not, comment out the line:

ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;

But it seems that the ExchangeService calls directly the server without passing trough the proxy... what am I missing?

Thanks

like image 488
Alessandro Avatar asked Mar 08 '18 09:03

Alessandro


1 Answers

Try to remove bypassonlocal attribute altogether from your proxy configuration in web.config. There is an issue with setting this attribute along with scriptLocation.

For more info: https://blogs.msdn.microsoft.com/rickrain/2011/03/25/why-scriptlocation-may-not-work-when-pointing-to-a-proxy-script-file-in-your-application-config-file/

Also the web.config default proxy configuration should be sufficient so you can remove any proxy setting in your code.

Maybe that's the case here.

UPDATE: Specifying pac script location in proxyaddress instead of scriptLocation attribute in web.config should resolve this issue.

like image 55
arekzyla Avatar answered Sep 21 '22 01:09

arekzyla