I am creating a new MVC application and trying to set up Windows authentication but when I attempt to log in it denies me.
I don't think this is related to IIS Express or my browsers as I have other MVC applications using Windows Authentication that work fine. After looking at the trade logs it appears it is attempting to connect via Anonymous Authentication which baffles me because if have this in my web.config:
<authentication mode="Windows"/>
In my project properties I have also enabled Windows Authentication and disabled Anonymous Authentication.
I'm not sure what other info to include so let me know if more is needed. Losing my mind here, please help.
UPDATE:
Closer but still not working,
Removing the following from my web config fixed my Anonymous Authentication issue:
<authorization>
</authorization>
However now in my stack trace I see the following lines that do not appear in my other working Windows authentication apps:
AspNetAppDomainEnter Data1="/LM/W3SVC/45/ROOT-1-130825677814817784" 14:36:37.272
AspNetStartHandler Data1="ASP.global_asax", Data2="Start" 14:36:37.272
AspNetPipelineEnter Data1="System.Web.Security.WindowsAuthenticationModule" 14:36:37.272
AspNetPipelineLeave Data1="System.Web.Security.WindowsAuthenticationModule"
And this is the error I get:
ModuleName ManagedPipelineHandler
Notification EXECUTE_REQUEST_HANDLER
HttpStatus 401
HttpReason Unauthorized
HttpSubStatus 0
ErrorCode The operation completed successfully.
(0x0)
ConfigExceptionInfo
Not really sure what they mean at this point but it seems like they may be related to my problem some how.
UPDATE:
My remaining issue appears to be something specific to the active directory groups I am using. Users do not seem to be in the roles I have in my FilterConfig so I am being denied access, when I remove all filter roles I get in.
RESOLVED:
For completeness I will add what fixed my authorization issue. For some reason there was a problem adding multiple Roles in my FilterConfig like so:
filters.Add(new HandleErrorAttribute());
filters.Add(new System.Web.Mvc.AuthorizeAttribute() { Roles = Auth.ROLE1 });
filters.Add(new System.Web.Mvc.AuthorizeAttribute() { Roles = Auth.ROLE2 });
filters.Add(new System.Web.Mvc.AuthorizeAttribute() { Roles = Auth.ROLE3 });
But when I created a roll-up group and added them all within AD to that group, then just authorized the single group like so:
filters.Add(new HandleErrorAttribute());
filters.Add(new System.Web.Mvc.AuthorizeAttribute() { Roles = Auth.ALL_ROLES });
It fixed my authorization issue.
You probably need to force authentication to happen, probably just add the <authorization /> tag to your <system.web> element:
<authorization>
<deny users="?" />
</authorization>
Related
I have created an MVC 5 Application with Windows Authentication,
<authentication mode="Windows" />
<authorization>
<deny users="?" />
</authorization>
I have below code to get user's Display name along with I also want to do validation,
protected void Session_Start(object sender, EventArgs e)
{
if (Context.User != null)
{
MapUserADDetails(Context.User);
}
}
private void MapUserADDetails(IPrincipal user)
{
using (HostingEnvironment.Impersonate())
using (var domain = new PrincipalContext(ContextType.Domain, "test.com"))
using (var usr = UserPrincipal.FindByIdentity(domain, user.Identity.Name))
{
if (usr == null)
{
return;
}
Session.Add("UserDisplayName", usr.DisplayName);
}
}
Now I am hosted this app to IIS with only windows authentication enabled. When I am browsing it, it's prompt for userName and Password,
Question,
Even I am entering wrong username/password or even doesn't fill anything, it's able to fetch Display Name.
How to restrict this? User/Pass must be validate against the AD. Please suggest. Thanks!
It sounds as IIS configuration issue and not the code.
To troubleshoot:
check if IE behaves differently
make sure that IIS has only Windows authentication enabled and not e.g. anonymous (see Receiving login prompt using integrated windows authentication)
make sure that the page has no other resources (e.g. images) used from other location that requires authentication (maybe that prompt is not for the page but for resources embedded into it)
check browser settings (e.g. in IE that site might need to be added into Intranet Zone, or "Automatically logon with current username and password" is not enabled)
You're not actually validating any username/password combination. UserPrincipal.FindByIdentity only checks if the user is found in AD.
To validate user credentials, you would need to check:
using (var domain = new PrincipalContext(ContextType.Domain, "test.com"))
{
bool authenticated = domain.ValidateCredentials(user.Identity.Name, password);
if (!authenticated)
{
// Do stuff
}
}
You can check MSDN for more info.
I am using MVC4, ASP.NET 4.5, C#
I want to add code to my onAuthorization method in global.asa to identify whether the connection is SSL or not, if not then to issue a permanent redirect to a SSL domain. I am using another domain that is SSLed.
In my Login controller I have code along the lines of :
[HttpGet]
public virtual ActionResult LogOn(string Error="")
{
if (Request.IsSecureConnection)
{
return View(viewModel);
}
else
{
return RedirectPermanent("https://www.mysslapp.com/logon");
}
}
I want to add this same functionality to the onAuthorization method so that when actions, covered by the [authorize] filter are called then they must also be accessed by a SSL connection. So I believe my global.asa code needs changing. However it will not accept "Request.IsSecureConnection", as the context is different.
My "pseudo" Global.asa onAuthorization routine is:
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (Request.IsSecureConnection)
{
base.OnAuthorization(filterContext);
}
else
{
RedirectPermanent("https://www.mysslapp.com/logon");
}
}
The above will not work, but it describes what I am trying to achieve. I would appreciate help on how I need to change the above code to make it work, such that any "adventurous" use of urls, on a non SSL connection will automatically redirect to the SSL site logon page.
Thanks in advance.
EDIT1
Think I have the first bit:
filterContext.HttpContext.Request.IsSecureConnection
EDIT2
if (filterContext.HttpContext.Request.IsSecureConnection)
{
base.OnAuthorization(filterContext);
}
else
{
filterContext.Result = new RedirectResult("https://www.mysslapp.com");
}
I think your main issue is that you have 2 separate concerns and you are trying to achieve both in one go. Your 2 concerns are:
Making every URL of domain A 301 redirect to the same URL on domain B
Making domain B redirect all requests to HTTPS
The first one is really easy. Create a new IIS site for domain A, install the IIS rewrite module, add this web.config to the site, and then adjust your DNS (if necessary) to make the site live.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpRedirect
enabled="true"
destination="https://www.mysslapp.com$V$Q"
exactDestination="true"
httpResponseStatus="Permanent" />
<httpProtocol>
<redirectHeaders>
<!-- This is to ensure that clients don't cache the 301 itself -
this is dangerous because the 301 can't change when put in place
once it is cached -->
<add name="Cache-Control" value="no-cache"/>
</redirectHeaders>
</httpProtocol>
</system.webServer>
</configuration>
NOTE: The above configuration is for IIS 7.5. I am not sure if it will work on other versions of IIS.
Now none of the users of domain B will incur the performance hit of the redirect rule, so all is good.
For redirecting your users of domain B to HTTPS, you should not use 301. Why? Because not all browsers respond to 301.
You should also not only allow HTTPS on the domain, but allow both HTTP and HTTPS. Why? Because your users that type myssldomain.com will get an ugly error message instead of a fast redirect to you HTTPS protected site.
So the simple solution to making your whole site redirect to HTTPS is to use the RequireHttps attribute and register it as a global filter. The RequireHttpsAttribute uses a 302 redirect when a request comes in that is not secure.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new RequireHttpsAttribute());
filters.Add(new HandleErrorAttribute());
}
}
As for the AuthorizeAttribute, you should leave that out of the equation altogether unless you need some customization that deals with authorization.
i working on windowsbased authentication my config looks like this
web.config
authorization
allow roles="Administrator"
allow roles="SuperUser" />
deny users="*"
authorization
in global.asax.cs
void Application_AuthenticateRequest(object sender, EventArgs e)
{
string message = string.Empty;
if (HttpContext.Current.User.Identity.IsAuthenticated)
message = HttpContext.Current.User.Identity.Name + " login successfully !";
else
message = HttpContext.Current.Request.UserHostAddress + " login failure !";
}
this works perfect in cassini. i am able to login to the application.
when i host it in IIS 7 with windows Authentication enabled.
i am getting Object reference not set to an instance of an object.
this is because for some reason HttpContext.Current.User is null
for some reason the user is not set in the httpcontext.
please help me to solve this
thanks in advance.
Managed pipeline in iis apppool is set to Integrated.
with this one turned on the httpcontext is not set on Application_AuthenticateRequest event.
this is little bit premature to access the httpcontext.
so i moved the logic to the appropriate place inside my landing controller method and it worked.
Thanks.
Is it possible to setup Authorization based on the zone of the request? Basically it is an intranet type application, with only little sensitive information.
If the request is performed from within the organization, it is fine to allow anonymous users.
However if it is an external request, they should get the 401 Authorization challenge.
External requests are coming from a single firewall, so an IP/IP range should be fine to specify if it is an external or internal request.
Currently it is configured for Windows authentication in the web.config file.
<authentication mode="Windows" />
<authorization>
<deny users="?" />
</authorization>
It would be easier to handle this rule directly at your firewall.
As an alternative you could configure IP Security at your IIS level and filter by client IP.
But if you have no control over the firewall you could write a custom Authorize attribute that will check the incoming IP address and allow/deny the request:
public class IpBasedAuthorizeAttribute: AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var ip = httpContext.Request.UserHostAddress;
return IsAllowed(ip);
}
private bool IsAllowed(string ip)
{
// TODO: do your checks here and return true or false
// depending on whether the IP address is allowed to
// access the application or not
throw new NotImplementedException();
}
}
and then you could either decorate individual controllers/actions with this attribute or register it as a global authorization attribute if you want it to apply to all requests:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new IpBasedAuthorizeAttribute());
}
I have custom error pages setup using
<customErrors mode="On" defaultRedirect="~/Home/Error">
<error statusCode="404" redirect="~/Home/PageNotFound" />
</customErrors>
I created a page that throws and exception and I get redirected to the correct error pages.
However I am noticing these errors in elmah on the production webserver:
System.InvalidOperationException The view 'Error' or its master was
not found or no view engine supports the searched locations. The
following locations were searched:
~/Areas/Football/Views/Draft/Error.aspx
~/Areas/Football/Views/Draft/Error.ascx
~/Areas/Football/Views/Shared/Error.aspx
~/Areas/Football/Views/Shared/Error.ascx ~/Views/Draft/Error.aspx
~/Views/Draft/Error.ascx ~/Views/Shared/Error.aspx
~/Views/Shared/Error.ascx ~/Areas/Football/Views/Draft/Error.cshtml
~/Areas/Football/Views/Draft/Error.vbhtml
~/Areas/Football/Views/Shared/Error.cshtml
~/Areas/Football/Views/Shared/Error.vbhtml ~/Views/Draft/Error.cshtml
~/Views/Draft/Error.vbhtml ~/Views/Shared/Error.cshtml
~/Views/Shared/Error.vbhtml
Why is it looking for the error page elsewhere? I deleted ~/Views/Shared/Error.cshtml and added my custom error page at ~/Home/Error since i specified a new default in my config file.
Any ideas?
Thanks.
MVC projects by default adds the HandleErrorAttribute in the Global.asax.cs file
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
This filter is executed when an unhandled exception is thrown. It sets the view as Error. Hence MVC runtime tries to render that view. But in your case, there is no such view. So it again throws another exception which is handled by ASP.NET runtime and shows your error page that you have configured in Web.Config file.
You can create your own exception filter and register it.
I ended up taking out the registration of HandleErrorAttribute in Global.asax and just using the <customErrors> section. ELMAH now properly logs errors, and I'm able to specify custom error pages.
Am I missing something?
You can also make sure that the HandleErrorAttribute is not registered by removing it from the global filters, using the Remove method:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Remove(new HandleErrorAttribute());
/* ... your other filters */
}
}
For future readers of this post, note that Elmah adds its own HandleErrorAttribute so is also expecting the Error.cshtml view. Note that I also installed the Elmah.MVC NuGet package but that is just used to set it up properly.
Yes, just noticed on nuget.org that Elmah.MVC is responsible for adding the HandleErrorAttribute:
Painless integration of ELMAH functionality into ASP.NET MVC
Application. Just drop the package inside your ASP.NET MVC application
and access /elmah URL. It will also install global HandleError filter,
that guarantees all unhandled errors are logged (even if customError
turned "On").
To disable ELMAH's HandleErrorAttribute add the following line to the appSettings section of your Web.Config file:
<!-- language: lang-xml -->
<add key="elmah.mvc.disableHandleErrorFilter" value="true" />