Reputation: 91
I am building an ASP.NET Core API (1.1) in Visual Studio Code using Windows Impersonation for authentication. (The API allows researchers to create Samples
.) I am using this impersonation middleware to handle authentication, which passes on the user identity nicely when connecting to the underlying SQL Server database.
However, for some write actions, I would like to add the name of the user who created the object as a value to the database (i.e. the name of the researcher creating the sample). I can't seem to make it work. I based my solution on the responses to these questions: How to get the current logged in user Id ASP.NET Core and ASP.NET Core Identity does not inject UserManager<ApplicationUser> and this tutorial, even though they seem to be aimed at storing the user identities in separate tables in the SQL server database, which is not my intent. I only need the username of the user sending the request.
I get the following error message on the line var user = await GetCurrentUserAsync();
in my controller.
The 'await' operator can only be used within an async method.
Consider marking this method with the 'async' modifier
and changing its return type to 'Task<IActionResult>'
My question is twofold:
How can I fix this error?
Is there an easier/better way to get the User Identity in my situation.
My Controller
file
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using System.Security.Claims;
using MyAPI.Model;
using MyAPI.Services;
namespace MyAPI.Controllers
{
[Route("api/[controller]")]
public class SamplesController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);
[HttpPost]
public IActionResult Post([FromBody] Sample sample)
{
var user = await GetCurrentUserAsync();
var userId = user?.Id;
// I abstracted the underlying logic of creating a sample in the database
//because it is quite complex and doesn't seem relevant to this problem
CreateSample(sample, userId);
}
}
}
Startup.cs
file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using MyAPI.Model;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Impersonate.AspNetCore.Windows;
namespace MyAPI
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add framework services.
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseWindowsImpersonation(options => { options.Enabled = true; });
app.UseMvc();
}
}
}
MyAPI.Model.ApplicationDbContext
file
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
namespace TrinityAPI.Model
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
{
Database.EnsureCreated();
}
}
}
MyAPI.Model.ApplicationUser
file
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
namespace TrinityAPI.Model
{
public class ApplicationUser : IdentityUser
{
}
}
Upvotes: 1
Views: 1632
Reputation: 4986
With Windows authentication enabled and inside the code for a controller action, you can find out information about the current user by going to the User object on the HttpContext property. For example, the following action should show domain\username for the current user.
public IActionResult Index()
{
return Content(HttpContext.User.Identity.Name);
}
When using Windows authentication, your are correct in thinking that you don't want to use ASP.NET Identity. You can remove the ApplicationDbContext class as well as the AddIdentity call in your Startup class.
Upvotes: 2