1

So I have this bit of code that gets a token from Azure Active Directory. When this bit runs the first time after the server starts, it's crashing with a null reference exception. The exception occurring is recorded in the output window, but the exception itself isn't caught by my code.

When I use the debugger to step through this code, it simply does not continue past AcquireTokenAsync - It terminates there, with the exception recorded in output, but it's not caught by my try/catch, and there's no way to recover.

There's nothing in here that's null, so I'm at a bit of a loss to explain, especially why this only occurs once after the server is restarted.

Code

    private static async Task<string> getToken() 
    {
        string aadInstance = ConfigurationManager.AppSettings["Authority"];
        string tenant = ConfigurationManager.AppSettings["Tenant"];
        string clientId = ConfigurationManager.AppSettings["ClientId"];
        string clientSecret = ConfigurationManager.AppSettings["ClientSecret"];
        string resource = ConfigurationManager.AppSettings["GraphResourceUri"];
        string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
        AuthenticationContext authContext = new AuthenticationContext(authority);
        ClientCredential clientCredential = new ClientCredential(clientId, clientSecret);
        try
        {
            AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCredential); 
       //anything past here never runs
            return result.AccessToken;
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.StackTrace);
        }
        return "";
    }

Edit:

Okay I have a stack trace after messing with exception settings: StackTrace " at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)"

Scuba Steve
  • 1,541
  • 1
  • 19
  • 47
  • If `authContext.AcquireTokenAsync` causes a `NullReferenceException` the `catch` block should then get control and the Exception should be logged (unless for some reason `Debug.WriteLine` also causes an `Exception` in which case make sure that Debug is from `System.Diagnostics` namespace and not something else). – Igor Jan 30 '19 at 19:31
  • The only other reason this would not happen is if the executing code is not the same as your code base. This can happen if the .dll/.exe that is executing is older than you are expecting or is not copied to the output directory or something similar. You would be surprised how frequently this happens. – Igor Jan 30 '19 at 19:32
  • @Igor - Thanks for this. I'll try to do a clean and rebuild. I might try to update system.web too - maybe that's part of my problem. – Scuba Steve Jan 30 '19 at 19:35
  • The exception block is definitely not getting control though - it's not when I step through. – Scuba Steve Jan 30 '19 at 19:37
  • @Igor - I updated every library that handles our backend that could possibly be related to System.Web, including the ADAL libs. Still having the issue. Did a clean and rebuild too, to be safe. – Scuba Steve Jan 30 '19 at 19:56
  • Okay so best I can work out that this *only* occurs while the server is spinning up. Once the startup is done this doesn't occur. It's a little baffling that the server can receive requests, but at the same time throws un-catchable exceptions that terminate code. – Scuba Steve Jan 30 '19 at 20:05
  • Nope I was wrong. It seems to occur after the server is done spinning up too. And only when called from the one controller. If the source is from other controllers, the issue doesn't occur. – Scuba Steve Jan 30 '19 at 20:16
  • Yep - I'm 100% sure. I've got a breakpoint set on AcquireTokenAsync, it runs to there. I step in to the method, and it fails after that point. I've edited the question with a stack trace. – Scuba Steve Jan 30 '19 at 20:37
  • what if you switch to using `... = authContext.AcquireTokenAsync(resource, clientCredential).Result` – GregH Jan 30 '19 at 20:38
  • Oh I'll try that. Give me a sec. – Scuba Steve Jan 30 '19 at 20:40
  • @GregH - That did it. I guess it had something to do with the HTTP context inside the awaiter. Not the first time I've seen weirdness there. – Scuba Steve Jan 30 '19 at 20:47
  • Think you were encountering a deadlock issue. This likely explains it https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html here's a thread on SO discussing the issue further https://stackoverflow.com/questions/15021304/an-async-await-example-that-causes-a-deadlock – GregH Jan 30 '19 at 20:48
  • @ScubaSteve check my answer for further details – GregH Jan 30 '19 at 21:09

1 Answers1

1

You are experiencing a deadlock issue that you can overcome by using:

AuthenticationResult result = authContext.AcquireTokenAsync(resource, clientCredential).Result;

or

AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCredential).ConfigureAwait(false);

This issue is caused by blocking on async code.

For a deeper dive into these topics, you can check here and here

The issues described in these links are happening somewhere internal to the call to await authContext.AcquireTokenAsync(resource, clientCredential); (code not posted so I can't tell you exactly where)

GregH
  • 5,125
  • 8
  • 55
  • 109
  • These would be inside the ADAL library (as that's what lib is being called by that method). But yes, I'm inclined to agree. Thanks for the suggestion, it did work to resolve the issue. – Scuba Steve Jan 30 '19 at 23:07
  • I don't necessarily think it's a deadlock, but what can happen is that inside an awaited item, you can actually lose the static HttpContext (or perhaps it was never there to begin with ). – Scuba Steve Jan 30 '19 at 23:10