AzureAD / azure-activedirectory-library-for-dotnet

ADAL authentication libraries for .net
http://aka.ms/aaddev
MIT License
358 stars 214 forks source link

NullReferenceException AdalHttpClient and Network Timeout #1253

Closed AntonioSCoelho closed 5 years ago

AntonioSCoelho commented 6 years ago

Version of ADAL used: c# ADAL 3.19.8 Which platform has the issue: net45

I'm using the following code:

        const string RedirectUri = "https://login.live.com/oauth20_desktop.srf";
        const string ResourceUri = "https://analysis.windows.net/powerbi/api";
        const string AuthorityUri = "https://login.windows.net/common/oauth2/authorize";

                LoggerCallbackHandler.LogCallback = ActiveDirectoryLogCallback;
                LoggerCallbackHandler.PiiLoggingEnabled = true;

                result = authContext.AcquireTokenAsync(
                    ResourceUri,
                    ClientId,
                    new Uri(RedirectUri),
                    new PlatformParameters(PromptBehavior.Always)).Result;

With that code, I get the Microsoft login page. Enter the user email, I'm redirect to the the company's login page and then the windows just closes and I get the error below.

Exception:

LoggerBase.cs: Exception type: System.NullReferenceException
   à Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Http.AdalHttpClient.<GetResponseAsync>d__22`1.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   à Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Http.AdalHttpClient.<GetResponseAsync>d__22`1.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Http.AdalHttpClient.<GetResponseAsync>d__21`1.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à Microsoft.IdentityModel.Clients.ActiveDirectory.InstanceDiscovery.<DiscoverAsync>d__8.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à Microsoft.IdentityModel.Clients.ActiveDirectory.InstanceDiscovery.<GetMetadataEntryAsync>d__5.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Instance.Authenticator.<UpdateFromTemplateAsync>d__47.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.<PreRunAsync>d__64.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.<RunAsync>d__57.MoveNext()

`

jennyf19 commented 6 years ago

@AntonioSCoelho - You might be running into a threading issue. We recommend using the async/await pattern and not .Result(). See this information on async controller actions for more information. Let us know if this fixes the issue for you.

AntonioSCoelho commented 6 years ago

I changed to the below code and I got the same error.

    public void btLogin_Click()
        {
            Login();
        }
        public async void Login()
        {
            var authContext = new AuthenticationContext(AuthorityUri);
            var result = await authContext.AcquireTokenAsync(
                    ResourceUri,
                    ClientId,
                    new Uri(RedirectUri),
                    new PlatformParameters(PromptBehavior.Always));
        }
jmprieur commented 6 years ago

@AntonioSCoelho

  1. Are you trying to sign-in with a live account using ADAL.NET ? I see that your redirect URL is https://login.live.com/oauth20_desktop.srf, which, I believe is for the Live SDK? If you do want to sign-in users with Live accounts, please use MSAL.NET ?

  2. I also noticed that the authority you have set is https://login.windows.net/common/oauth2/authorize. you should not specify the endpoint, just the authority that is It should be https://login.onmicrosoft.com./common/ if you want a multi-tenant application (or https://login.onmicrosoft.com./{tenanId}). For more details please see the description of the constructor for AuthenticationContext: see Authority Validation

but thanks for reporting we can definitively make progress in throwing a meaningful exception in that case.

AntonioSCoelho commented 6 years ago

This is used on an enterprise windows forms application, so I need that redirect URL.

The idea of the application is to list PowerBI Reports and Dashboard and I so need to connect to multiple company emails.

I saw an example in Microsoft docs and they were using that authority also. (I will try to find that and link it here)

The code with the .Result() was working in production for several months. But since around two weeks ago I have some customers that are not able to login. Maybe something change in the Microsoft’s login workflow ?

jmprieur commented 6 years ago

@AntonioSCoelho could you please enable logging by following this article: Logging? and share the logs with us?

AntonioSCoelho commented 6 years ago

@jmprieur Attached are the files from two different customers. If you need more information let me know. Log1.txt - This company uses single sign-on Log2.txt - This company uses multi factor authentication and single sign-on. This is a different error, but with the same authentication problem. (I don't know if the type of authentication could be an issue..)

shahbikash commented 6 years ago

I am facing a similar issue, using 3.19.3 i have detailed the issue in #1206

henrik-me commented 6 years ago

@AntonioSCoelho : did you try to update the Authority uri (https://login.windows.net/common/ or the new alias https://login.microsoftonline.com/common) as suggested by @jmprieur ? Also do you only see this issue occasionally?

AntonioSCoelho commented 6 years ago

@henrik-me Haven't tried to change the authority. Only happens with some customers (tried with different accounts inside the same organization and the same result). Others are able to login just fine.

henrik-me commented 6 years ago

@AntonioSCoelho : can you share some characteristics of the customers/accounts where this doesn't work (e.g. special federation setup or other elements).

AntonioSCoelho commented 6 years ago

@henrik-me The only information I have is: One uses single sign-on and the other one uses multi factor authentication and single sign-on.

hewey23 commented 6 years ago

I am having the same issue. Strangely, it is only with 2 out of 100 users.

2018-10-02 10:08:21.784532-0300 MooseExpense.iOS[3385:62476] 2018-10-02T13:08:21.7844200Z: e1859466-cd0c-4635-b6f6-d7c6c54dbf2e - LoggerBase.cs: Network timeout, Exception type: System.Threading.Tasks.TaskCanceledException Information 2018-10-02T13:08:21.7844200Z: e1859466-cd0c-4635-b6f6-d7c6c54dbf2e - LoggerBase.cs: Network timeout, Exception type: System.Threading.Tasks.TaskCanceledException Information 2018-10-02T13:08:21.7855200Z: e1859466-cd0c-4635-b6f6-d7c6c54dbf2e - LoggerBase.cs: Network timeout, Exception message: A task was canceled. 2018-10-02 10:08:22.786834-0300 MooseExpense.iOS[3385:62638] 2018-10-02T13:08:22.7866910Z: e1859466-cd0c-4635-b6f6-d7c6c54dbf2e - LoggerBase.cs: Retrying one more time.. Information 2018-10-02T13:08:22.7866910Z: e1859466-cd0c-4635-b6f6-d7c6c54dbf2e - LoggerBase.cs: Retrying one more time.. Information 2018-10-02T13:08:22.7885270Z: e1859466-cd0c-4635-b6f6-d7c6c54dbf2e - LoggerBase.cs: Retrying one more time..

hewey23 commented 6 years ago

Here is the code that times out:

        LoggerCallbackHandler.LogCallback = Log;
        LoggerCallbackHandler.PiiLoggingEnabled = true;

        var authContext = new AuthenticationContext(Keys.AadAuthority);
        if (authContext.TokenCache.ReadItems().Any() == true)
        {
            var test = authContext.TokenCache.ReadItems();
            authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
        }
        var authResult = await authContext.AcquireTokenAsync(
            Keys.AzureServiceUrl /* The resource we want to access  */
            ,Keys.AadClientId   /* The Client ID of the Native App */
            ,returnUri               /* The Return URI we configured    */
            ,new PlatformParameters(RootView)
            //,UserIdentifier.AnyUser
            //,Keys.AadDomainHint
        ).ConfigureAwait(false);

        return authResult.AccessToken;
bgavrilMS commented 6 years ago

I had a look at the Null Ref stack trace provided and I cannot repro locally, nor can I find anything that stands out. The offending method is here: https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/blob/e60bdfc732f4bd8f113fe06101a4e1cc03a2d9d2/src/Microsoft.IdentityModel.Clients.ActiveDirectory/Internal/Http/HttpClientWrapper.cs#L74

So a couple of thoughts to get this moving:

  1. Upgrade to ADAL v4, as the HTTP stack has been reworked. I know it's in preview but we will GA in a few weeks. You can at least test to see if the problem repros. Note that v4 is pretty much compatible with v3, but please make sure you rebuild.

  2. I can add a lot of logging to that method and give you a private DLL to try to narrow down the issue.

Hopefully #1 is acceptable for your, otherwise I am happy to help with #2.

StephanBis commented 6 years ago

We are still experiencing this problem. Upgraded to v4.3.0 today and we still get the network timeout exception. We tried rebuilding the application as @bgavrilMS explained in his answer above, but this did not solve the issue.

hewey23 commented 6 years ago

Upgrading to 4.0.0-preview fixed my issue.

Thanks for your help...

bgavrilMS commented 6 years ago

@hewey23 - I had a look at the stack trace for the network timeout exception:

An error occurred while sending the request. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:8888

To me this looks like a misconfigured proxy. Could you have a look at this "Using ADAL with a Proxy" ?

bgavrilMS commented 5 years ago

Closing, hopefully the proxy details solved the issue.