1

This is not a duplicate question ( as far as I researched ). My problem is everything works nice when I run ASP.NET Core 2.1 MVC application in VS 2019 but when I deploy to local IIS and launch my application in browser it is not working. My operating system is Windows 10.

I have below turned on in IIS

enter image description here

I am doing below to get username of person who launched my ASP.NET Core 2.1 MVC application in browser.

In Properties -> launchSettings.json

"windowsAuthentication": true,
 "anonymousAuthentication": false,

In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
   services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

In Helper.cs

public static string GetUserName(IHttpContextAccessor httpContextAccessor)
{
  string userName = string.Empty;
  if(httpContextAccessor != null &&
     httpContextAccessor.HttpContext != null &&
     httpContextAccessor.HttpContext.User != null &&
     httpContextAccessor.HttpContext.User.Identity != null)
    {
        userName = httpContextAccessor.HttpContext.User.Identity.Name;
        string[] usernames = userName.Split('\\');
        userName = usernames[1].ToUpper();
    }
        return userName;
}

In MyController.cs

public class MyController : Controller
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyController(IHttpContextAccessor httpContextAccessor)
    {
      _httpContextAccessor = httpContextAccessor;            
    }

    [HttpPost]
    public JsonResult CreateOrder([FromBody] OrderModel model)
    {
      string username = Helper.GetUserName(_httpContextAccessor);
      .....
    }
}

When I run my application in VS 2019 everything is fine but when I publish my application to IIS and launch my application in browser I get error due to httpContextAccessor.HttpContext.User.Identity.Name null.

I also tried various ways like FindFirst using Claims but all those work good when I run in VS 2019 but not publish my application to IIS and launch my application in browser. What mistake I am doing.

Thanks in advance.

Ziggler
  • 3,361
  • 3
  • 43
  • 61
  • 1
    If you found the solution, post your own answer and accept it. – Lex Li Sep 26 '19 at 22:47
  • @LexLi.. I posted my solution. I will accept after 2 days. – Ziggler Sep 27 '19 at 00:00
  • Why downvote for this. – Ziggler Sep 27 '19 at 00:00
  • Possible duplicate of [How to get the current Windows user with ASP.NET Core RC2 MVC6 and IIS7](https://stackoverflow.com/questions/38233974/how-to-get-the-current-windows-user-with-asp-net-core-rc2-mvc6-and-iis7) – Jabez Sep 27 '19 at 08:59
  • Unless I do steps 1 and 2 in my answer below IIS..authentication nothing worked. All those posts never say about it. I am OK. I got it fixed and I am sure they will lot of people who will have this issue and this post will help. – Ziggler Sep 30 '19 at 23:20
  • Did you define something more before you added [Authorize]? InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. for me the username is null – user7849697 Nov 28 '19 at 09:54

3 Answers3

6

I found the solution.

I did below in my IIS. Double click on Authentication.

enter image description here

enter image description here

Properties -> launchSettings.json and web.config did not fix the issue.

In Starup.cs,

public void ConfigureServices(IServiceCollection services)
{
  services.AddHttpContextAccessor();
}

In Helper.cs

public static string GetUserName(IHttpContextAccessor httpContextAccessor)
{
   string userName = string.Empty;
   if(httpContextAccessor != null &&
      httpContextAccessor.HttpContext != null &&
      httpContextAccessor.HttpContext.User != null &&
      httpContextAccessor.HttpContext.User.Identity != null)
      {
        userName = httpContextAccessor.HttpContext.User.Identity.Name;
        string[] usernames = userName.Split('\\');
        userName = usernames[1].ToUpper();
      }
      return userName;
}

In MyController.cs - I added Authorize tag to my action method.

public class MyController : Controller
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyController(IHttpContextAccessor httpContextAccessor)
    {
      _httpContextAccessor = httpContextAccessor;            
    }

    [HttpPost]
    [Authorize]
    public JsonResult CreateOrder([FromBody] OrderModel model)
    {
      string username = Helper.GetUserName(_httpContextAccessor);
      .....
    }
}

Now it works good when I debug in VS 2019 and after I publish to IIS and others calling my application in browser.

Ziggler
  • 3,361
  • 3
  • 43
  • 61
1

Huge thanks to @Ziggler for his answer. Almost all research I came across suggested modifying the web.config and launchSettings.json as well as Enable Windows Authentication and Disable the Anonymous Authentication in the IIS configuration screen which all did not fix the issue. The below did fix my issue...

Pulled the windows authenticated username out and cleaned it up before returning the value

 public class Helper : IHelper{

    private readonly ILogger<Helper> _logger;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public Helper(ILogger<Helper> logger, IHttpContextAccessor httpContextAccessor) { 
        _logger = logger;
        _httpContextAccessor = httpContextAccessor;
    }

    public int GetSSO()
    {
        try
        {
            //Remove DSM
            string temp = Regex.Replace(_httpContextAccessor.HttpContext.User.Identity.Name, @"[DSM]", "");
            //Remove special characters
            temp = Regex.Replace(temp, @"[^\w\.@-]", "");
            //Convert string to int
            int sso = Int32.Parse(temp);

            return sso;
        }
        catch (Exception e)
        {
            _logger.LogError("::::Error Getting SSO:::: " + e);
            return 000000000;
        }
    }
GRU119
  • 1,028
  • 1
  • 14
  • 31
0

Windows Auth must be enabled separately for the IIS site. Likely, you haven't done this, so automatic authorization is not occurring, and hence, the user name is null.

That said, you should not inject IHttpContextAccessor into a controller. The HttpContext is already available via HttpContext directly. Additionally, your helper is completely useless here, as you're merely replacing:

HttpContext.User.Identity.Name

With:

Helper.GetUserName(HttpContext)

In fact, you can actually just use User.Identity.Name, since the principal is stored in the User property on the controller by default.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • I need Helper since I need to use this logic in so many places and I do not want to duplicate it. I have so many controllers and almost each method in my controller needs UserName to log it. If I must not inject IHttpContextAccessor how will my helper class with get access to it? If you see my IIS picture in my question I checked Windows Authentication. Is there anything else I need to do. I am looking at HttpContext. – Ziggler Sep 26 '19 at 16:27
  • There's no logic. It's just `User.Identity.Name`. – Chris Pratt Sep 26 '19 at 16:29
  • I am getting null and I posted what I did in my question. – Ziggler Sep 26 '19 at 16:31
  • I moved GetUserName from Helper.cs to MyController.cs but it did not work. – Ziggler Sep 26 '19 at 16:39