I have created a web app in .net core 3.1 and authenticate users against Azure AD. After successful authentication I'm fetching user information from Microsoft Graph API. All are working fine locally but whenever I'm publishing it to Azure, it is also working fine for the users who are logged In at the first time but getting exception if the users already logged In (Previous Logged In) into the web app. This application is also working fine if the user logged Out who is already logged In and logged In again. If the user already logged In and trying to get user details through Microsoft Graph, getting exception:
Code: generalException
Message: An error occurred sending the request.
(1b2e028d)
2021-07-23T03:33:27.7510101+00:00 80010cc2-0000-da00-b63f-84710c7967bb [INF] at Microsoft.Graph.HttpProvider.SendRequestAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
at Microsoft.Graph.HttpProvider.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
at Microsoft.Graph.BaseRequest.SendRequestAsync(Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
at Microsoft.Graph.BaseRequest.SendAsync[T](Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
at Microsoft.Graph.UserRequest.GetAsync(CancellationToken cancellationToken)
at SentimentAnalysisApp.Controllers.HomeController.Index() in D:\Workspaces\Controllers\HomeController.cs:line 70 (15cafa0a)
Here is my Startup.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
string[] initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
services
// Use OpenId authentication
.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
// Specify this is a web app and needs auth code flow
.AddMicrosoftIdentityWebApp(Configuration)
// Add ability to call web API (Graph)
// and get access tokens
.EnableTokenAcquisitionToCallDownstreamApi(options =>
{
Configuration.Bind("AzureAd", options);
}, initialScopes)
// Use in-memory token cache
// See https://github.com/AzureAD/microsoft-identity-web/wiki/token-cache-serialization
.AddInMemoryTokenCaches()
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"));
// Require authentication
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
// Add the Microsoft Identity UI pages for signin/out
.AddMicrosoftIdentityUI();
//services.AddSingleton<AppData>();
services.AddScoped<AppData>();
services.AddRazorPages();
var path = Directory.GetCurrentDirectory();
services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo($"{path}\\DataProtectionKeys\\Keys.xml"));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
var path = Directory.GetCurrentDirectory();
loggerFactory.AddFile($"{path}\\SentimentLogs\\Sentiment_Log.txt");
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
}
Here is my Controller class:
[Authorize]
public class HomeController : Controller
{
public HomeController(IConfiguration config, ILogger<HomeController> logger,
GraphServiceClient graphServiceClient,
ITokenAcquisition tokenAcquisition,
IDataProtectionProvider provider, AppData appData,
IMemoryCache memoryCache)
{
_logger = logger;
_graphServiceClient = graphServiceClient;
_tokenAcquisition = tokenAcquisition;
_protector = provider.CreateProtector("Encrypt");
_appData = appData;
_config = config;
}
[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
public async Task<IActionResult> Index()
{
try
{
//Here I'm fetching logged in user details and getting exception if the user
//already logged in.
LoggedInUser = await _graphServiceClient.Me.Request().GetAsync();
_appData.LoggedInUser = LoggedInUser.DisplayName;
string token = await _tokenAcquisition.GetAccessTokenForUserAsync(GraphConstants.Scopes);
}
catch (MicrosoftIdentityWebChallengeUserException)
{
return Challenge();
}
catch (Exception ex)
{
_logger.LogInformation(ex.Message);
_logger.LogInformation(ex.StackTrace);
Console.WriteLine(ex.Message);
//return Challenge();
}
return View(_appData);
}
}
Any help would be much appreciated!
I am unable to reproduce your problem based on the official sample code. But from your error message, I see that your error message is from your local pc.
at SentimentAnalysisApp.Controllers.HomeController.Index() in D:\Workspaces\Controllers\HomeController.cs:line 70 (15cafa0a)
Your description is that everything is normal in local, but after the release, the problem appeared.
So I give the following suggestions and suggest troubleshooting: