-
Notifications
You must be signed in to change notification settings - Fork 208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug] : NullReferenceException when acquiring a token for a user in a server-side Blazor app. #157
Comments
I don't think it's a duplicate as the stack trace indicates a different point in the stack for the exception. Stack trace for #136: at Microsoft.Identity.Web.HttpContextExtensions.GetTokenUsedToCallWebAPI(HttpContext httpContext) in D:\a\1\s\src\Microsoft.Identity.Web\HttpContextExtensions.cs:line 29 Stack trace for my issue (included in "Actual behavior" of submitted ticket): at Microsoft.Identity.Web.TokenAcquisition.CreateRedirectUri() From review of #136, I thought the issue may be related to this line in var request = CurrentHttpContext.Request; where a root issue of a null HttpContext may be the similarity between #136 and this issue. |
I also have this same issue (works perfectly locally but Azure Web App fails). |
|
I do think there is a case with Blazor that may be an issue across the board. As described in the issue report, everything works as expected in the OnGet() method of the Blazor page; i.e. I can use The reason (I believe) it works locally is that HttpContext is available for subsequent requests by the way local development environments work - it fails in Azure by the way browsers communicate via web socket to the App Service. I also implemented a rather clunky workaround where in the OnGet() method I set a property on the model with the value of the AD Token that I then inject as a CascadingParameter into the components, which is then passed to my service method as a method arg. A lot of plumbing/passing of the AD Token where it would be ideal to use Microsoft.Identity.Web to request a token when/where needed. |
@gwgrubbs you are right with the bit about HttpContext. The workaround is to have a service that caches the token for you. I am doing this here This is using Microsoft.Identity.Client so it won't work here directly. Need to modify the process to get the token but it IS doable |
@jennyf19 I still get a NullReferenceException at TokenAcquisition.cs:line 220 |
@schmid37 : could you please provide the stack trace? cc: @jennyf19 |
@gwgrubbs I'm unable to repro this issue. We now have web app blazor templates, which you can try as well. Do you have repro you can share? |
@jennyf19 - I pulled your branch and corrected breaking changes. I reviewed the sample project "BlazorServerSideWeb-CSharp", specifically to look at Startup.cs to see how to "correctly" configure Microsoft.Identity.Web[.UI]. Here's what I have in my Startup.cs: services.AddMicrosoftWebAppAuthentication(Configuration, "AppAzureAd")
.AddMicrosoftWebAppCallsWebApi(Configuration, Configuration.GetSection("Api:Scopes").Get<List<string>>(), "AppAzureAd")
.AddInMemoryTokenCaches(); When running with assembly references to those from your branch, everything works fine locally. However, running in Azure I get the following (as reported in Chrome console): [2020-07-20T20:14:12.249Z] Error: System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Identity.Web.TokenAcquisition.BuildConfidentialClientApplicationAsync() in D:\src\microsoft-identity-web\src\Microsoft.Identity.Web\TokenAcquisition.cs:line 337
at Microsoft.Identity.Web.TokenAcquisition.GetOrBuildConfidentialClientApplicationAsync() in D:\src\microsoft-identity-web\src\Microsoft.Identity.Web\TokenAcquisition.cs:line 326
at Microsoft.Identity.Web.TokenAcquisition.GetAccessTokenForUserAsync(IEnumerable`1 scopes, String tenant, String userFlow) in D:\src\microsoft-identity-web\src\Microsoft.Identity.Web\TokenAcquisition.cs:line 211
at OBFUSCATED.Web.App.Service.AppService.AddAuthorizationHeaderAsync(HttpRequestMessage request, String accessToken) in D:\src\OBFUSCATED\src\OBFUSCATED.Web.App\Service\AppService.cs:line 90
at OBFUSCATED.Web.App.Service.AppService.<>c__DisplayClass4_0`1.<<GetAsync>b__0>d.MoveNext() in D:\src\OBFUSCATED\src\OBFUSCATED.Web.App\Service\AppService.cs:line 38
--- End of stack trace from previous location where exception was thrown ---
at OBFUSCATED.Net.Http.HttpClientService.SendRequestAsync[TReturn](HttpRequestMessage message, Func`2[] configure) in D:\src\OBFUSCATED\src\OBFUSCATED\Net\Http\HttpClientService.cs:line 149
at OBFUSCATED.Net.Http.HttpClientService.GetAsync[TReturn](Action`1 urlPathBuilder, Func`2[] configure) in D:\src\OBFUSCATED\src\OBFUSCATED\Net\Http\HttpClientService.cs:line 47
at OBFUSCATED.Web.App.Service.AppService.GetAsync[T](String accessToken, Action`1 urlPathBuilder) in D:\src\OBFUSCATED\src\OBFUSCATED.Web.App\Service\AppService.cs:line 38
at OBFUSCATED.Web.App.Service.AssetService.GetPageAsync(String accessToken, PageModel page, String filterToFundId) in D:\src\OBFUSCATED\src\OBFUSCATED.Web.App\Service\AssetService.cs:line 22
at OBFUSCATED.Web.App.Pages.Asset.FetchCurrentPage() in D:\src\OBFUSCATED\src\OBFUSCATED.Web.App\Pages\Asset.razor:line 160
at OBFUSCATED.Web.App.Pages.Asset.OnInitializedAsync() in D:\src\OBFUSCATED\src\OBFUSCATED.Web.App\Pages\Asset.razor:line 96
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync() In my service, I'm using the following code to acquire a token, which caused the exception: await tokenAcquisition.GetAccessTokenForUserAsync(apiOptions.Value.Scopes);
|
Thanks @gwgrubbs, did you try with the current master branch? Changes were made to not use the CurrentHttpContext.User where possible. There is an Optional claims principal representing the user that can be passed in. |
@jennyf19 I just pulled master branch (18c4950), and I'm still getting the exception; now getting it where @schmid37 was seeing it:
microsoft-identity-web/src/Microsoft.Identity.Web/TokenAcquisition.cs Lines 220 to 226 in 18c4950
I do see the optional claims principal in the method signature, the problem is I have no access to this value in the context of a web socket - not without a bunch of hoops and tying in to the oidc events (as @isaacrlevin did). My hope was you guys could figure out the lift between DI, scoped services, token caching, etc. to be able to manage all of this internally. |
@gwgrubbs thanks for the reply. we are working on a solution for this. will keep you posted here. |
@jennyf19 works so far :) |
@jennyf19 Sometimes I get an Exception: blazor.server.js:19 [2020-07-22T14:44:30.900Z] Error: System.NullReferenceException: Object reference not set to an instance of an object. When I delete the cookies and do a reload, Everything works fine. Is this a problem related to the actual chanages? The |
@jennyf19 I concur with @schmid37 that it is working so far. I haven't experienced the issue you see, but I think I know what the issue is. if you have a stale cookie and call |
@gwgrubbs & @schmid37 glad to hear it's working, thanks for confirming. we are aware of the redirect issue, it's because blazor doesn't have the challenge method, so we're trying to come up with a work around. |
@schmid37 this is the only issue for tracking at the moment. we're trying to get this into our next release (today or tomorrow), but if we run out of time (we have an external deadline), then I will close this and open a new issue, ping you both here so you know. sound good? |
@jennyf19 sounds good to me! Thx for the support 💪🏻 |
@gwgrubbs @jaimunday @isaacrlevin @schmid37 This is included in Microsoft Identity Web 0.2.1-preview release. |
Which Version of Microsoft Identity Web are you using ?
Microsoft Identity Web 0.1.2-preview
Where is the issue?
This is a new application that is a server-side Razor application calling a protected Web API. The application works as expected locally, but fails with a
NullReferenceException
when running as an Azure App Service. The failure occurs when trying to retrieve a token for a user (GetAccessTokenForUserAsync
). The request to get a token for the user occurs in a lower-level HttpClient service when retrieving the token to add as an Authorization header. The HttpClient service is injected into the Blazor page (@Inject). As a test, I've added code to the OnGet() method of the Blazor page (which runs on first access of a page from the site), and the same code works as expected both locally and in Azure (GetAccessTokenForUserAsync
returns a valid token with no exception).I have confirmed that the following values are correctly configured:
I have confirmed the application has been registered correctly in Azure AD with valid value(s) for:
Given I can run the application locally with no exceptions, I don't think I have missing or invalid configuration. I also don't think this issue has anything to do with the Web API itself, this exception occurs simply trying to get a token from the cache and/or from MSAL prior to communication with the (protected) Web API.
Repro
Startup.cs
Blazor Page method that works as expected (no exceptions, token acquired) on first page request:
HttpClient setting the authorization header (
GetAccessTokenForUserAsync
works locally, but fails in Azure):Expected behavior
I expect to be able to acquire a valid token for the user at any point during the "request" lifecycle.
Actual behavior
The following stack trace:
Possible Solution
At a minimum, better exception handling that leads me to the actual error.
The text was updated successfully, but these errors were encountered: