sherlock1982 / ews-managed-api

https://www.nuget.org/packages/Microsoft.Exchange.WebServices.NETStandard/
Other
99 stars 44 forks source link

(401) Anonymous Request Disallowed on Ubuntu 14 #14

Closed IInvocation closed 6 years ago

IInvocation commented 6 years ago

Hi,

first about the project i'm currently migrating: Small AspNetCore-application previously hosted on Windows (outside of the domain) that shall be migrated to an Ubuntu-Server (obviously outside of the domain).

Using ews-managed-api in version 1.0.15 - i'm getting the ServiceRequestException with "(401) Anonymous Request Disallowed" - although i'm specifying: Domain, User and Password

Is there any known problem on linux about this? Would an upgrade to version 1.1 help here?

The code i'm using to authenticate is: _service = new ExchangeService(_options.Version) { Url = new Uri(_options.ServiceUrl), Credentials = new WebCredentials(_options.Username, _options.Password, _options.Domain), PreAuthenticate = true }; (The options i'm specifying match the ones i've given the windows-server. Domain is specified like 'mydomain.local')

I'd be happy about a little feedback :)

Stacktrace: Microsoft.Exchange.WebServices.Data.ServiceRequestException: The request failed. The remote server returned an error: (401) Anonymous Request Disallowed. ---> System.Net.WebException: The remote server returned an error: (401) Anonymous Request Disallowed. at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at System.Net.WebRequest.<>c.b__37_2(IAsyncResult iar) at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endFunction, Action1 endAction, Task1 promise, Boolean requiresSynchronization) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Exchange.WebServices.Data.EwsHttpWebRequest.d__10.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.d__45.MoveNext() --- End of inner exception stack trace --- at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.d__45.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.d__43.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Exchange.WebServices.Data.SimpleServiceRequestBase.d__1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest1.d6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Exchange.WebServices.Data.ExchangeService.d24.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Exchange.WebServices.Data.ExchangeService.d25`1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at FluiTech.CallRouting.Ews.EwsHelper.d8.MoveNext() in C:\dev\BitBucket\FluiTec\CallRouting\src\FluiTech.CallRouting.Ews\EwsHelper.cs:line 78 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at FluiTech.CallRouting.Ews.EwsHelper.d9.MoveNext() in C:\dev\BitBucket\FluiTec\CallRouting\src\FluiTech.CallRouting.Ews\EwsHelper.cs:line 92 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at FluiTech.CallRouting.AspCoreHost.Controllers.ApiControllers.CalendarController.d4.MoveNext() in C:\dev\BitBucket\FluiTec\CallRouting\src\FluiTech.CallRouting.AspCoreHost\Controllers\ApiControllers\CalendarController.cs:line 67 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ObjectMethodExecutor.d38`1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d27.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d25.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d20.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Builder.RouterMiddleware.d4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.d3.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.d3.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.d7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.d4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d__18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d__18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at IdentityServer4.Hosting.IdentityServerMiddleware.d__4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at IdentityServer4.Hosting.FederatedSignOutMiddleware.d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at IdentityServer4.Hosting.AuthenticationMiddleware.d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at IdentityServer4.Hosting.BaseUrlMiddleware.d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d__18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d__18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.d__6.MoveNext() `

sherlock1982 commented 6 years ago

ExchangeService.UseDefaultCredentials should be set to false. Default true. Otherwise your login/password/domain will be simply ignored.

Also please note that your url should end like this: /ews/exchange.asmx. Otherwise you're doing something wrong.

IInvocation commented 6 years ago

Hi, thank you for the fast response.

I changed my code to: _service = new ExchangeService(_options.Version) { UseDefaultCredentials = false, Url = new Uri(_options.ServiceUrl), Credentials = new WebCredentials(_options.Username, _options.Password, _options.Domain), PreAuthenticate = true }; However - i still get the same exception i mentioned before. (Which doesnt really surprise me, since the code i'm using on Ubuntu is exactly the same as on Windows - which is working fine without ever having set UseDefaultCredentials=false;...

The project itself is checked and tested well on Windows.

ServiceUrl is = "ServiceUrl": "https://mail.myprivatedomain.de/ews/exchange.asmx", // secret

sherlock1982 commented 6 years ago

Can you try with http? I had an issue with https access from Linux. That's with onpremise Exchange. Office365 works of course

IInvocation commented 6 years ago

I don't think our admin will enable http-access to the exchange-server, since that would probably require reconfiguration of the reverse-proxy in front of it that was done external. But i'll try. (It's indeed a selfhosted exchange-server version 2013)

Any tips on where to look if i were to debug myself? (Of course after i upgrade to NetCore 2...)

sherlock1982 commented 6 years ago

I'm not saying it's for production. Just to try with HTTP to see if there's an issue with HTTPS only.

What I found so far:

  1. Office 365 works from anywhere
  2. HTTPS on premise from Linux is not working. Also from ssldump I see that HTTPS connection was actually ok. I would use ssldump to decode real HTTP requests out of HTTPS and see what's going on. Probably HTTP authentication header is missing for some reason.
  3. It doesn't matter if it's NET Standard 1.0 or 2.0

Please could you send me update when you will fix it so I can merge.

sherlock1982 commented 6 years ago

I think here's the explanation.

IInvocation commented 6 years ago

Hi,

thank you for lookin into this – i’ll be happy to try this out.

I guess u’ll stick to targeting netstandard2?

sherlock1982 commented 6 years ago

Yes of course. Though obviously it doesn't help. I will investigate as soon as I have time. Probably first approach will be to disable auto redirects and do them manually supplying credentials.

sherlock1982 commented 6 years ago

Seems I know the answer. Linux uses only Digest authentication. Digest authentication is a bit outdated so it's probably disabled somewhere on your server. Enable it and it should work.

IInvocation commented 6 years ago

I enabled digest authentication for the "EWS"-application in IIS which should probably be enough - however - this didnt change anything. I guess i'll just set up an internal bridge-server publishing the relevant functionality using a JsonWebApi.

sherlock1982 commented 6 years ago

Could you find any logs from Exchange side? Linux does something wrong with Digest authentication according to capture. Would be nice to see what server doesn't like

svrooij commented 6 years ago

I've got the same problem, the server got Negotiate, NTLM and Basic enabled. You can get some logging of the requests by enabling the Trace, specifically the EwsRequestHttpHeaders are interesting. It seems like the Basic header doesn't get set in any request.

This doesn't solve the real problem, but it is a work-around.

var ews = new ExchangeService(ExchangeVersion.Exchange2013_SP1,TimeZoneInfo.Local){
    Credentials = new WebCredentials(username,password), //credentials are required
    UseDefaultCredentials = false, // don't use the default ones
    PreAuthenticate = false, // don't preauthenticate (this seems broken)
    AcceptGzipEncoding = true,
    // TraceEnabled = true,
    // TraceEnablePrettyPrinting = true,
    // TraceFlags = TraceFlags.EwsRequest | TraceFlags.EwsRequestHttpHeaders | TraceFlags.All,
};

// and then just set the correct header yourself.
var bytes = System.Text.Encoding.ASCII.GetBytes($"{username}:{password}");
var headerValue = "Basic " + Convert.ToBase64String(bytes);
ews.HttpHeaders.Add("Authorization", headerValue);

// I recommend you to only use this on a https server. Because the credentials are send in clear text!!
IInvocation commented 6 years ago

I can confirm this is work-around works well. Authentication is no longer a problem.

ststeiger commented 6 years ago

This workaround doesn't work for me, the exchange-server doesn't have basic-authenticaton enabled. The problems is CURL (used by .NET) having problems with NTLMv2 (on Linux), it cannot have multiple authenticate-headers. If you have multiple, e.g.

WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM

then it won't work...

So if basic-authentication isn't enabled, you need to proxy all requests, and remove the second authenticate header in the proxy...

So long, waiting for a fix in .NET framework/runtime.

AlexZeitler commented 6 years ago

Fix from @svrooij did work for me as well.

DreamTreem commented 10 months ago

Another 5 cents. This solution helped my team to connect a .NET Core app, which uses EWS Managed API library and is running on Linux, to the Exchange Server which has only NTLM and does not have basic authentication.

Essentially net core uses the underlying OS to handle http calls. Before, on Linux libCurl was used, but the newer SocketsHttpHandler uses gss, which doesn't come with ntlm support (at least not in the 'microsoft/dotnet:2.2-aspnetcore-runtime-stretch-slim' image). To fix this you need to install an extra library in your container, using the docker file. Right after FROM microsoft/dotnet:2.2-aspnetcore-runtime-stretch-slim (Or whatever image you use) on the next line add the following: RUN apt-get update && apt-get install -y --no-install-recommends apt-utils gss-ntlmssp

22tb commented 2 months ago

Thanks @DreamTreem . Your linked solution worked!