I am trying to get some graph to get return some user attributes from Entra. I need to use graphClient.Me.GetAsync()
.
Update: My end result is that I need to use var result = await graphClient.Users["{user-id}"].GetAsync((requestConfiguration) => { requestConfiguration.QueryParameters.Select = new string []{ "displayName","givenName","postalCode","identities" }; });
to get some attributes that graphClient.Me.GetAsync()
does not return, and I believe that is only supported with Microsoft.Graph 5.61, but I could be wrong.
When I run my project from Visual Studio I get prompted for my Entra credentials, then I get this error message:
An unhandled exception occurred while processing the request.
TypeLoadException: Could not load type 'Microsoft.Graph.IAuthenticationProviderOption' from assembly 'Microsoft.Graph.Core, Version=3.1.22.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxx'.
Here is my setup - I have added these packages:
Microsoft.Graph v.5.61
Microsoft.Identity.Web 3.2.2
Microsoft.Identity.Web.MicrosoftGraph v. 3.2.2
Added to appsettings.json
:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "yourdomain.onmicrosoft.com",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id",
"ClientSecret": "your-client-secret",
"CallbackPath": "/signin-oidc"
}
}
Added to Program.cs
:
using Microsoft.Identity.Web;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
// Add authentication and Microsoft Identity
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
// Add Graph API client
builder.Services.AddMicrosoftGraph(options =>
{
options.Scopes = "User.Read"; // Ensure this scope is granted in Azure portal
});
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
And this is my controller:
[Authorize]
public class HomeController : Controller
{
private readonly GraphServiceClient _graphClient;
public HomeController(GraphServiceClient graphClient)
{
_graphClient = graphClient;
}
public async Task<IActionResult> Index()
{
// Get the user's information
var user = await _graphClient.Me.GetAsync();
// Access the user's email
var email = user.Mail ?? user.UserPrincipalName;
ViewBag.Email = email;
return View();
}
}
Here is the csproj file
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Graph" Version="5.61.0" />
<PackageReference Include="Microsoft.Identity.Web" Version="3.2.2" />
<PackageReference Include="Microsoft.Identity.Web.GraphServiceClient" Version="3.2.2" />
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="3.2.2" />
</ItemGroup>
</Project>
Any ideas on what I am doing wrong?
I have tried different versions of the packages, different code in the Program.cs
.
To fix the error, I uninstalled the Microsoft.Graph
package and updated the code in Program.cs and HomeController.cs to retrieve user attributes from Entra using Microsoft Graph.
.csproj :
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" NoWarn="NU1605" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.10" NoWarn="NU1605" />
<PackageReference Include="Microsoft.Identity.Web" Version="2.19.1" />
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="2.19.1" />
<PackageReference Include="Microsoft.Identity.Web.UI" Version="2.19.1" />
<PackageReference Include="Microsoft.Identity.Web.DownstreamApi" Version="2.15.2" />
</ItemGroup>
Program.cs :
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
var builder = WebApplication.CreateBuilder(args);
var initialScopes = builder.Configuration["DownstreamApi:Scopes"]?.Split(' ') ?? builder.Configuration["MicrosoftGraph:Scopes"]?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
.AddInMemoryTokenCaches();
builder.Services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
HomeController.cs :
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Graph;
using Microsoft.Identity.Web;
namespace WebApplication15.Controllers
{
[Authorize]
public class HomeController : Controller
{
private readonly GraphServiceClient _graphClient;
public HomeController(GraphServiceClient graphClient)
{
_graphClient = graphClient;
}
[AuthorizeForScopes(ScopeKeySection = "MicrosoftGraph:Scopes")]
public async Task<IActionResult> Index()
{
var user = await _graphClient.Me.Request().GetAsync();
ViewData["GraphApiResult"] = user.UserPrincipalName;
return View();
}
[AuthorizeForScopes(ScopeKeySection = "MicrosoftGraph:Scopes")]
public async Task<IActionResult> GetUserDetails(string userId)
{
var result = await _graphClient.Users[userId]
.Request()
.Select("displayName,givenName,postalCode,identities")
.GetAsync();
ViewData["DisplayName"] = result.DisplayName;
ViewData["GivenName"] = result.GivenName;
ViewData["PostalCode"] = result.PostalCode;
ViewData["Identities"] = result.Identities;
return View();
}
}
}
appsettings.json :
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "<domain>",
"TenantId": "<tenantID>",
"ClientId": "<clientID>",
"CallbackPath": "/signin-oidc"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read User.ReadBasic.All"
}
}
index.cshtml :
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
<hr />
<div>
<h2>Graph API Result - Current User</h2>
<div><strong>User Principal Name:</strong> @ViewData["GraphApiResult"]</div>
</div>
<hr />
<div>
<h2>Graph API Result - User Details</h2>
<form method="get" action="/Home/GetUserDetails">
<label for="userId">Enter User ID:</label>
<input type="text" id="userId" name="userId" required />
<button type="submit">Get User Details</button>
</form>
<div>
<h3>User Details:</h3>
<p><strong>Display Name:</strong> @ViewData["DisplayName"]</p>
<p><strong>Given Name:</strong> @ViewData["GivenName"]</p>
<p><strong>Postal Code:</strong> @ViewData["PostalCode"]</p>
<h4>Identities:</h4>
<ul>
@if (ViewData["Identities"] is List<Microsoft.Graph.ObjectIdentity> identities && identities.Count > 0)
{
foreach (var identity in identities)
{
<li>
<strong>Sign-in Type:</strong> @identity.SignInType <br />
<strong>Issuer:</strong> @identity.Issuer <br />
<strong>Issuer Assigned ID:</strong> @identity.IssuerAssignedId
</li>
}
}
else
{
<li>No identities found.</li>
}
</ul>
</div>
</div>
_UserDetails.cshtml :
<p><strong>Display Name:</strong> @ViewData["DisplayName"]</p>
<p><strong>Given Name:</strong> @ViewData["GivenName"]</p>
<p><strong>Postal Code:</strong> @ViewData["PostalCode"]</p>
<h4>Identities:</h4>
<ul>
@if (ViewData["Identities"] != null)
{
var identities = (System.Collections.Generic.IList<object>)ViewData["Identities"];
foreach (var identity in identities)
{
<li>@identity</li>
}
}
else
{
<li>No identities found.</li>
}
</ul>
GetUserDetails.cshtml :
@{
ViewData["Title"] = "User Details";
}
<h2>User Details</h2>
<p><strong>Display Name:</strong> @ViewData["DisplayName"]</p>
<p><strong>Given Name:</strong> @ViewData["GivenName"]</p>
<p><strong>Postal Code:</strong> @ViewData["PostalCode"]</p>
<h4>Identities:</h4>
<ul>
@if (ViewData["Identities"] is List<Microsoft.Graph.ObjectIdentity> identities && identities.Count > 0)
{
foreach (var identity in identities)
{
<li>
<strong>Sign-in Type:</strong> @identity.SignInType <br />
<strong>Issuer:</strong> @identity.Issuer <br />
<strong>Issuer Assigned ID:</strong> @identity.IssuerAssignedId
</li>
}
}
else
{
<li>No identities found.</li>
}
</ul>
Output :
After successfully logging in, I got the below page. Then, I entered the user object ID and clicked on Get User Details as shown below.
User attributes :