I've an ASP.NET Core web application. Users can login with username and password or with Azure AD.
In a page with many info I want to show an info from Graph (e.g. Unread emails counter) only for Azure AD users. Other users simply can view the page, without the "Unread emails counter" info.
I don't understand how to make it work.
The problem is that Graph works only if I decorate the page with
[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)]
but to allow other users to access the same page I cannot use that attribute.
Both
[Authorize(AuthenticationSchemes = $"{OpenIdConnectDefaults.AuthenticationScheme},{CookieAuthenticationDefaults.AuthenticationScheme}")]
and
[AllowAnonymous]
[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)]
works for other users but do not works for Azure AD users because Graph throw exception
InvalidOperationException: IDW10503: Cannot determine the cloud Instance. The provided authentication scheme was ''. Microsoft.Identity.Web inferred 'Cookies' as the authentication scheme. Available authentication schemes are 'Cookies,OpenIdConnect'.
Here some code for your reference:
Authentication
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddNegotiate()
.AddMicrosoftIdentityWebApp(builder.Configuration, configSectionName: "Authentication:AzureAD");
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
var app = builder.Build();
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
The Razor Page
[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)]
[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
public class GraphCMSModel : PageModel
{
private readonly GraphLogic _graphLogic;
public string Message { get; set; } = string.Empty;
public GraphCMSModel(GraphLogic graphLogic)
{
_graphLogic = graphLogic;
}
public async Task OnGetAsync()
{
if (AuthHelper.IsAzureAdAuthenticated)
{
var messages = await _graph.Me.MailFolders["Inbox"].Messages
.Request()
.Filter("isRead ne true")
.GetAsync();
Message = $"You have {messages.Count} unread messages";
}
else
{
Message = "No Graph for you";
}
}
}
I've found a way to tell GraphServiceClient what authentication schema to use using WithAuthenticationScheme method:
var messages = await graph.Me.MailFolders["Inbox"].Messages
.Request()
.WithAuthenticationScheme(OpenIdConnectDefaults.AuthenticationScheme)
.Filter("isRead ne true")
.GetAsync();