问题
I have seen many same or similar questions, and tried all their answers if there was one, but none of those works for me.
I'm using this example from Microsoft's Github account as my project base.
It works well for just signing in users.
The project has 1 WebApi, 1 Angular App.
Then I followed this Microsoft example to add code to call Graph API. Here is the controller code:
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class BillsController : ControllerBase
{
static readonly string[] scopeRequiredByApi = new string[] { "access_as_user" };
readonly ITokenAcquisition tokenAcquisition;
readonly WebOptions webOptions;
public BillsController(ITokenAcquisition tokenAcquisition,
IOptions<WebOptions> webOptionValue)
{
this.tokenAcquisition = tokenAcquisition;
this.webOptions = webOptionValue.Value;
}
[HttpGet]
[AuthorizeForScopes(Scopes = new[] { Constants.ScopeUserRead, Constants.ScopeMailRead })]
public async Task<IActionResult> Profile()
{
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
var subject = string.Empty;
try
{
// Initialize the GraphServiceClient.
Graph::GraphServiceClient graphClient = GetGraphServiceClient(new[] { Constants.ScopeUserRead, Constants.ScopeMailRead });
var me = await graphClient.Me.Request().GetAsync();
// Get user photo
var messages = await graphClient.Me.MailFolders.Inbox.Messages.Request().GetAsync();
subject = messages.First().Subject;
return Ok(subject);
}
catch (System.Exception ex)
{
throw ex;
}
}
private Graph::GraphServiceClient GetGraphServiceClient(string[] scopes)
{
return GraphServiceClientFactory.GetAuthenticatedGraphClient(async () =>
{
string result = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
return result;
}, webOptions.GraphApiUrl);
}
}
For Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// Setting configuration for protected web api
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddProtectedWebApi(Configuration);
services.AddWebAppCallsProtectedWebApi(Configuration, new string[] { Constants.ScopeUserRead, Constants.ScopeMailRead })
.AddInMemoryTokenCaches();
services.AddOptions();
services.AddGraphService(Configuration);
// Creating policies that wraps the authorization requirements
services.AddAuthorization();
services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));
services.AddControllers();
// Allowing CORS for all domains and methods for the purpose of sample
services.AddCors(o => o.AddPolicy("default", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
// Since IdentityModel version 5.2.1 (or since Microsoft.AspNetCore.Authentication.JwtBearer version 2.2.0),
// Personal Identifiable Information is not written to the logs by default, to be compliant with GDPR.
// For debugging/development purposes, one can enable additional detail in exceptions by setting IdentityModelEventSource.ShowPII to true.
// Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
app.UseDeveloperExceptionPage();
}
else
{
// 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.UseExceptionHandler("/error");
app.UseCors("default");
app.UseHttpsRedirection();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
On the Angular App, I added one button to call this Profile() controller action.
todo-view.component.ts
getEmails(): void {
this.service.getEmails().subscribe({
next: (emails: any) => {
alert(emails);
},
error: (err: any) => {
console.log("error happened~!");
console.log(err);
}
});
}
todo-view.component.html
<button (click)="getEmails();">Get Emails</button>
I added the below code into my Startup.cs and removed the AddWebAppCallsProtectedWebApi. services.AddProtectedWebApiCallsProtectedWebApi(Configuration).AddInMemoryTokenCaches();
Now it throws me a different error message:
来源:https://stackoverflow.com/questions/61524182/msal-net-no-account-or-login-hint-was-passed-to-the-acquiretokensilent-call