Why is ServiceSecurityContext.Current null in an MVC Controller? - asp.net-mvc-4

I have an ASP.NET MVC 4 project that's using Windows authentication in the Web.config like so:
<system.web>
<authentication mode="Windows" />
</system.web>
However, if I investigate ServiceSecurityContext.Current from a Controller method, it's null. Shouldn't it contain the authentication info of the user since I'm using Windows authentication?
The reason I'm trying to figure this out is because I would like to know what credentials CredentialCache.DefaultNetworkCredentials is using from a Controller method. From what I gathered by reading the MSDN article on the property, it uses the current security context's credentials... which is null.
Thanks for the help!

The ServiceContext classes is intended to be used inside WCF services. It has nothing to do with ASP.NET MVC.
Trying to use ServiceContext.Current inside an ASP.NET MVC application is like trying to use HttpContext.Current inside a console application => you get NULL.
The reason I'm trying to figure this out is because I would like to
know what credentials CredentialCache.DefaultNetworkCredentials is
using from a Controller method
Then you are looking for the User.Identity.Name property:
[Authorize]
public ActionResult Index()
{
string currentUser = User.Identity.Name;
...
}

Related

Blazor throwing error when using HttpContext

I want to get current windows user name when user opens the website. My application uses Blazor server-side. To get current username, I added:
In startup.cs:
services.AddHttpContextAccessor(); (under
ConfigureServices)
In razor page:
#inject IHttpContextAccessor httpContextAccessor
In razor page method:
string userName = httpContextAccessor.HttpContext.User.Identity.Name;
When I execute the code, the application throws an exception:
"An error has occurred. This application may no longer respond until reloaded."
I get this error only when I deploy on IIS. On local machine it works well.
I had a similar issue trying to access HttpContext for user information using Blazor. I found this here which was a life saver. HttpContext is NULL when running web app in IIS
All I had to do to solve the problem was to enable WebSockets in IIS.
Here are the steps: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-3.1#iisiis-express-support
If you were to change that string from
string userName = httpContextAccessor.HttpContext.User.Identity.Name
to
string userName = httpContextAccessor?.HttpContext?.User?.Identity?.Name??"Anonymous"
then it would probably work.
It's because your IIS settings are allowing anonymous access and so your Identity object is null.
You should check for the inner exceptions behind the application crash but that will be your issue. You need to prevent anonymous access on IIS to get the Windows authentication passed through.
To manage IIS refer here https://stackoverflow.com/a/5458963/12285843

Change LoginPath without ASP.NET Core Identity

Use cookie authentication without ASP.NET Core Identity
The login file is located at Pages/Account/Login.cshtml.
I wish to change to Pages/Index, but I am not able to change the LoginPath after trying various methods that I found using Google.
Try it with adding the following snippet inside the ConfigureServices method. It has to be placed behind your call of AddAuthentication().
services.ConfigureApplicationCookie(cookie =>
{
cookie.LoginPath = "/Index";
});

Regarding Authorize attribute usage in ASP.Net MVC 4

when we decorate any action with Authorize attribute then how MVC redirect to login form because my login controller name could be different and also view name also could be different. login view also could be stored in different folder instead of shared folder.
so tell me how MVC engine understand that it need to load login form when face Authorize attribute ?
how MVC engine would know where login form template is stored because it location could be different instead of shared folder?
how MVC engine would know what is login controller name if my login controller name is different ?
please discuss 3 points i asked here in details. thanks
The AuthorizeAttribute is a filter, which means that it can execute before the associated controller action. The AuthorizeAttribute performs its main work in the OnAuthorization method. If the user fails authentication, an HttpUnauthorizedResult action result is returned which produced an HTTP 401 status code. In previous versions of ASP.NET MVC the user redirected to the application login page defined in the application's web.config:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
In ASP.NET MVC 5, the redirection process is handled by OWIN middleware components. It redirects unauthenticated requests to a LoginPath value, which
defaults to "/Account/Login":
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType =
DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});

The Session object is null in ASP.NET MVC 4 webapplication once deployed to IIS 7 (W 2008 R2)

I developed an ASP.NET MVC 4 web application (.net 4.5) which runs fine in Visual Studio 2012. After deployment to IIS 7 on Windows Server 2008 R2, it seems like the HttpContext.Session object inside my controller is null. I created a simple test ASP.NET MVC 4 application to demonstrate the issue.
In my test app I have a simple Home Controller
public class HomeController : Controller
{
public ActionResult Index()
{
if ( HttpContext != null && HttpContext.Session != null )
{
HttpContext.Session[ "test" ] = "a string in session state";
ViewBag.Info = HttpContext.Session[ "test" ];
return View();
}
else
{
if ( HttpContext == null )
{
ViewBag.Info = "beeeeuuuuu - HttpContext = null!!!";
}
else if ( HttpContext.Session == null )
{
ViewBag.Info = "beeeeuuuuu - Session = null!!!";
}
return View();
}
}
}
My Index.chtml view lookes something like this:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
This is a simple test
<p>#ViewBag.Info</p>
So when I run the application I get what I was expecting:
Index
This is a simple test
a string in session state
But after I deploy the application to the web server the website gives me the following page indicating that the Session object is null:
Index
This is a simple test
beeeeuuuuu - Session = null!!!
The web application is deployed to the default website which runs under the ASP.NET v4.0 application pool (integrated pipeline).
I already reïnstalled ASP.NET on the server using aspnet_regiis -ir but this didn't help. The Session state is enabled (In Proc) at the ISS server. I hope anyone can help me out here cause I'm trying to solve this for quite some time.
Much thanks in advance and kind regards.
UPDATE: I also tested an ASP.NET MVC 4 build with .NET 4.0 instead of 4.5 and that has the same problem. I also deployed an ASP.NET Web Pages app (.NET 4.0) and that works fine (The HttpContext.Current.Session is not null in the code behind).
UPDATE II: I also tried to store the Session State in a database, which worked fine on my development machine but had the same problem on the production server (HttpContext.Session still returns null).
I found the solution. You have to add and remove the SessionStateModule:
<configuration>
...
<system.webServer>
...
<modules>
<remove name="Session" />
<add name="Session" type="System.Web.SessionState.SessionStateModule"/>
...
</modules>
</system.webServer>
</configuration>
I have no idea why Microsoft doesn't add this to the web.config of the project template?
I thought Session was null in my controller when I deployed my app, but I was wrong. It turned out I had missed the subtleties of a lambda expression. Though this wasn't the solution in the asker's case, this Q&A is highly ranked in searches, so I hope this answer might save someone else some time.
My controller originally contained something like this:
HostingEnvironment.QueueBackgroundWorkItem(ct => Foo(ct, Bar(Session)));
Bar is a static method that gets a value from the session, and it was throwing a NRE trying to access its parameter. I changed my controller code as follows, and all was well:
var bar = Bar(Session);
HostingEnvironment.QueueBackgroundWorkItem(ct => Foo(ct, bar));
The mystery is why the original code ever worked at all when testing on my local machine!

Use Anonymous authentication in MVC4 on single controller when the whole application uses Windows Authenticaion

I have an MVC4 Web application which uses Windows Authentication, that is in web.config I have
<authentication mode="Windows" />
And that works fine and everything is ok.
However now I need a controller (an Web API controller in fact) that should be accessed anonymously from a third party component. The problem is that every time I want to invoke this method it requests user credentials.
I tried putting AllowAnonymous attribute to controller and methods but it was not successful.
[AllowAnonymous]
public bool Get(string Called, string Calling, string CallID, int direction)
I checked on both IIS Express and IIS 8 with Anonymous authentication and Windows authentication enabled.
It seems that windows authentication precedes any other authentication and cannot be overridden.
Is there a way to accomplish this?
Add this to your Web.config. Here, my controller is named "WebhookController".
<location path="Webhook">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
See this KB article for more info.
Edit
- As Erik mentioned below, in MVC applications you should not use web.config <authorization> tags for security. Instead, use [Authorize] attributes. Doing so will allow your [AllowAnonymous] attributes to work correctly. You can read more about this here.
The accepted answer seems to be out of date, so...
In your web.config, remove these lines:
<authorization>
<deny users="?" />
</authorization>
In the solution explorer, click your project, then click f4 (or open the properties explorer). Enable Anonymous Authentication.
Now you're free to use the Authorize and AllowAnonymous Attributes. They're pretty straightforward, Authorize means the user needs to be authorized in order to access the action or controller, AllowAnonymous means the opposite. If an unauthorized user attempts to access a controller or action with the Authorize attribute, they'll be redirected to a login page. If you put Authorize on a controller it applies to all the controller's actions, except ones with AllowAnonymous.
web.config should not be touched as indicated here.
In order to achieve desired result AllowAnonymous and [Authorize] (and maybe some custom authorization attribute, if needed) should be used.
Steps to be performed:
Ensure IIS has both Anonymous Authentication and Windows Authentication configured for the web application / web site
All controllers should use [Authorize] attribute. This can be easily achieved if all inherit from a common controller class (e.g. BaseController / BaseApiController). E.g.:
[Authorize]
public class BaseController : System.Web.Mvc.Controller
{
}
[Authorize]
public class BaseApiController : System.Web.Http.ApiController
{
}
Add [AllowAnonymous] attribute to all actions that are supposed to be anonymous. E.g.:
[RoutePrefix("Api/Anonymous")]
[Authorize]
public class AnonymousController : ApiController
{
[HttpGet]
[Route("GetServiceStatus")]
[AllowAnonymous]
public string GetServiceStatus()
{
return "OK";
}
}