'c# Microsoft Graph permissions to read mails
I have the following list of permissions on Azure AD:
my ASP.NET Web Core app has the following config:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "https://xxxx.azurewebsites.net",
"TenantId": "common",
"ClientId": "e24xxxxxxf",
"ClientSecret": "RDYxxxxxmL",
"ClientCertificates": [
],
"ClientCapabilities": [ "cp1" ],
"CallbackPath": "/signin-oidc"
},
"DownstreamApi": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "mail.read mail.readbasic mail.readbasic.all user.read"
},
Program.cs:
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor()
.AddMicrosoftIdentityConsentHandler();
var config = builder.Configuration;
string[]? initialScopes = config.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(config.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(config.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
When I try to open page, page requested only base profile permissions and email address:
when I call
var inbox = await _graphServiceClient.Me.Messages.Request().GetAsync();
after approving these permissions, I get an error:
ServiceException: Code: InvalidMsaTicket Message: ErrorCode: 'PP_E_RPS_REASON_OFFERACTIONS_INVALID'. Message: ''
but it works fine for calling:
var currentUser = await _graphServiceClient.Me.Request().GetAsync();
Why mail reading is not requested and how to implement it?
Solution 1:[1]
I'm afraid you referred to this document.
Microsoft Graph permissions to read mails means we can use Ms graph api to read mails. So we need to pass the authentication first to get the consent to access the api. What you showed in your questions are the configurations to integrate azure ad authentication into your .net 6 web application, which will provide UI to let users sign in so that your application can call the api to get mails of the signed user. So you also need to add UI in your code.
After adding the authentication part, we also need to call the api, we can use graph SDK here. And you may check my code below/
Program.cs:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
string[]? initialScopes = config.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
builder.Services.AddMicrosoftIdentityWebAppAuthentication(config)
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(config.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
// Require authentication
builder.Services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
// Enables a UI and controller for sign in and sign out.
builder.Services.AddRazorPages().AddMicrosoftIdentityUI();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
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.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
appsetting.json, pls follow the document to register azure ad application, create client secret and configure authentication:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "client_id",
"Domain": "tenant_name.onmicrosoft.com",
"TenantId": "common",
"ClientSecret": "client_secret",
"CallbackPath": "/home/index"
},
"DownstreamApi": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read"
}
Controller, using graph SDK to query graph api:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Graph;
using Microsoft.Identity.Web;
using System.Diagnostics;
using WebMvcAzure.Models;
namespace WebMvcAzure.Controllers
{
[Authorize]
public class HomeController : Controller
{
private readonly GraphServiceClient _graphServiceClient;
private readonly ITokenAcquisition _tokenAcquisition;
public HomeController(GraphServiceClient graphServiceClient, ITokenAcquisition tokenAcquisition)
{
_graphServiceClient = graphServiceClient;
_tokenAcquisition = tokenAcquisition;
}
public IActionResult Index()
{
return View();
}
[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
public async Task<string> mailsAsync() {
string[] scopes = new string[] { "user.read" };
string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);
var mail = await _graphServiceClient.Me.Messages.Request().GetAsync();
return "success";
}
}
}
Don't forget to add a login view _LoginPartial.cshtml in the Shared folder and add the partial view into _layout.cshtml
@using System.Security.Principal
<ul class="navbar-nav">
@if (User.Identity.IsAuthenticated)
{
<li class="nav-item">
<span class="navbar-text text-dark">Hello @User.Identity.Name!</span>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignOut">Sign out</a>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignIn">Sign in</a>
</li>
}
</ul>
Test result:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |




