Formsauthentication should be disabled for a single page - c#

I have a problem with Formsauthentication and my ajax calls.
I like the way Formsauthenticaction works for a normal asp.net website.
However I have a page in my asp.net website which gets called using AJAX. This page will in some case set the Response StatusCode to Unauthorized (401).
Response.StatusCode = 401;
Response.End();
Now the Response should end and I would like to see this 401 statuscode propagated to the frontend. However Formsauthentication decides otherwise and changes this status to a 302 and redirects to the loginpage.
Thus I can not check for status 401 on my UI.
To inform you further: I am running an asp.net 4.0 website (Not MVC) on IIS 7.
I tried configuring my web.config with following node:
<location path="mypage.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
But I guess by setting the Unauthorized status triggers the Formsauthentication module nonetheless.

Here are a few proposed solutions from Phil Haack's blog.
Prevent Forms Authentication Login Page Redirect When You Don’t Want It

Related

Automatic Redirect on Authorize Failure Using IIS Automatic Authentication with ASP.NET Core MVC

I am creating a website in ASP.Net Core MVC and using IIS's automatic authentication to have users of the company automatically be validated through active directory. This is working as it should at the moment, however, I'd like to redirect users to a log in page if they can not be validated through IIS. I've seen other posts describing how to do this when using a normal authentication cookie, but not with this automatic authentication.
This is my current Configure Services method:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.Configure<IISServerOptions>(options =>
{
options.AutomaticAuthentication = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
So at the moment it is successfully locking out users who do not have AD authorization on a page marked [Authorize], I'd just like to redirect that locked out traffic to another page marked [AllowAnonymous]. Is there a way to modify the services.Configure method? So far I do not see anything.
What you're using is called Windows Authentication. The reference to AutomaticAuthentication just tells IIS to automatically set HttpContext.User with the user details (otherwise it doesn't, even if the authentication succeeded).
What you're looking for is really two authentication methods: For people with AD accounts (who are logged in with those accounts), log them in automatically using Windows Authentication. Otherwise, show a login screen and you can handle the authentication yourself.
I've done this before in ASP.NET MVC, but I haven't (yet) done it in ASP.NET Core. I'll describe what I did, but this isn't a complete solution since there's a missing piece for ASP.NET Core.
Use cookies for your main authentication method. Set it up like normal, with a login page where you validate the credentials and set the cookie.
Setup one controller action (lets say, /Login/SSO) that uses Windows Authentication. I did that using a location tag in the web.config. That is still likely the same in ASP.NET Core, I'm just not entirely sure how you pick up on that in the code. But the part in web.config would look something like this:
<location path="Login/SSO">
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="true"/>
<anonymousAuthentication enabled="false"/>
</authentication>
</security>
</system.webServer>
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
In the code for that action, assuming you can figure out how to grab the username from the Windows Authentication, you set the cookie and return a 200 OK (you don't need to return a view). If Windows Authentication fails, IIS will return a 401 on its own. (I think the <allow users="?"/> was just to prevent the cookie authentication from trying to redirect - but I can't remember)
The fancy trick is on the login page. Hide everything on the page by default. On page load, do an AJAX request to /Login/SSO. If it succeeds, then the user is logged in and you can forward them (via javascript) to the page they want. If it fails, just show the contents of the login page. That would look something like this (assuming you're using jQuery):
$(function() {
$.get("#Url.Action("SSO", "Login")").done(function(data) {
//success! forward to the page they want
window.location.replace(returnUrl);
}).fail(function() {
//failed - show login prompt
$("#loginBox").show();
});
});
With this setup, a user who can be authenticated using Windows authentication will hit the site, get redirected to the login page, the login page does a successful AJAX request that creates their cookie, and they get redirected back to the original page they wanted. Pretty seamless.

WCF - Disable browser authentication for client app

I have created a WCF OData Service using .NET4.5 with C#. In the application, there is a form Basic authentication implemented that uses ASP.NET Identity which works well.
Following is my code in the service app, where I intercept the authorization header and authenticate the request.
protected override void OnStartProcessingRequest(ProcessRequestArgs args)
{
bool isAuthenticated = CustomBasicAuth.Authenticate(HttpContext.Current);
if (!isAuthenticated)
{
args.OperationContext.ResponseHeaders.Add("WWW-Authenticate", "Basic");
HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true;
throw new DataServiceException(401, "Invalid login or password");
}
base.OnStartProcessingRequest(args);
}
So whenever I access the service app in browser, it would prompt for the browser login. This is great for testing purpose.
Then I have a web based client which calls the service. On invalid login, it returns the 401 error, which is expected and I can handle it. But it also prompts the browser login form. How can I suppress this form in client app. (Disabling browser properties is not an option)
You can deny access to the service / location for un-authenticated users, through web.config:
<configuration>
<location path="Path/To/Folder/YourService.svc">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
...
</configuration>
The same pattern can be applied to any aspx page, asmx classic web service, etc.

MVC3 app redirects to ReturnUrl=%2f

I am using Form Authentication in my MVC3 web app. I have added following in root web.config:
<authentication mode="Forms">
<forms name=".FormsAuth" loginUrl="~/Home/Index" timeout="2880" />
</authentication>
<authorization>
<deny users="?"/>
</authorization>
When I launch my app, it redirects to http://localhost:22888/Home/Index?ReturnUrl=%2f instead http://localhost:22888. If I remove line <deny users="?"> then it redirects correctly but then Context.User.Identity.Name gives no value after login.
Please help.
Take a look at Securing your ASP.NET MVC 4 App and the new AllowAnonymous Attribute.
You cannot use routing or web.config files to secure your MVC application (Any Version). The only supported way to secure your MVC application is to apply the Authorize attribute ...
Quote
MVC uses routes and does not map URLs to physical file locations like WebForms, PHP and traditional web servers. Therefore using web.config will definitely open a security hole in your site.
The product team will have a communication if this changes in the future, but for now it is without exception the rule.
Examples:
Start with the default ASP.Net MVC project (internet/intranet).
Edit the web.config adding:
<location path="Home">
<system.web>
<authoirzation>
<deny users="*">
</authoirzation>
</system.web>
</location>
Run the project, by default you will use the Default route /Home/Index and you see content, simply bypassing the web.config with no changes to the default template. Why? Because the ASP.Net pipeline is comparing the URL requested to the location specified in the web.config. However, after the Authorization Event has been executed in the pipeline the routing taking place (Default routing or custom routing) and allows access to the supposedly restricted area.
Additionally, any MVC Redirect() will also by-pass the same security measures as again the routing takes place after the Authorization Pipeline Event.
When I launch my app, it redirects to http://:22888/Home/Index?ReturnUrl=%2f instead http://:22888.
If you are using the default template, authorization stores the returnUrl and redirects back to /Home/Index with the value %2f which is /. You can update the RedirectToAction code in the AccountsController to not append the returnUrl if it is /.
This is correct behavior of the runtime.
You told the engine to deny the access to unauthenticated users and also that the login url is located at ~/Home/Index.
This is why when you navigate to the default url / the engine makes the browser go to the login page and passes the return url, encoded / in this case.
The question is then: what you want to do if the correct behavior bothers you.
I resolved this issue by performing two modifications:
I removed deny users='?' line from web.config file. But then I was getting null in Context.User.Identity.Name
In HttpPost Login method, I was redirecting user after successful authentication using return View("Home"). When I changed it to return RedirectToAction("Home") I got value in Context.User.Identity.Name
Although a little late to the show, if you're still having issues, remember to look down at the sections in your web.config for other authorization rules (correctly or incorrectly set). There are some situations where mis-configurations to a resource at the root or subdirectory could cause endless redirects.

website authorization behaving very unusually

I am using forms authentication in asp.net4. But the authorization is behaving very unusually.
Following is my web.config snippet-
<authentication mode="Forms">
<forms loginUrl="Login.aspx" timeout="2880" protection="All" path="/" />
</authentication>
<authorization>
<deny users="?"/>
<allow users="*"/>
</authorization>
When i try to open any web page i am redirected to Login page as expected. If close my browser i should be logged out, but thats not happening although i am setting persistentCookie=false as follow
FormsAuthentication.RedirectFromLoginPage(username, false);
Now after closing browser if a login again i am considered authenticated user, but if i clear cookie cache in my browser than i wont be considered authenticated user.
I am not setting cookie anywhere and i dont want persistent cookie, than why is this happening.
Please tell me if i am missing something.
Anobody know something related to this
I just found that this problem is only with Chrome 21.0, and not with Firefox 7.0 or Opera 11.4 (problem of authenticating even though session ends).
When you use authentication mode="Forms" your auth credentials stored in cookies by default. If you want to change this behaviour you can use cookieless="UseUri" attribute, than your credential will be stored in the URL. You can find more inforamtion forms Element for authentication.
timeout attribute specify how long cookies will be stored (in minutes) by default it is 30.

How to redirect a user back to where he was after login in asp.net mvc 3

I'm learning ASP.NET MVC3 and I'm now examining the user handling.
My first problem would be (I know there is a lot about this subject in other threads, I just fail to find a good one with MVC3) that I want the login page to redirect me where I came from, or where I was redirected from.
In php perhaps I would add this url to the querystring, maybe.
But I need a way to do this somehow automatically, and this is a so common design pattern I was wondering if there is a "built in" way to do this.
What would be the cleanest, or preferred way to do this?
Also when I'm redirecting to a login page which would be the best way for checking and storing the url which I'm redirected from? I would check for the referrer in the request object and spit it out in the url as "?redirect=protected.html" but I'm not even sure how to properly do this.
Any advice on this subject would be appreciated.
MVC works the same way as ASP.NET.
If you use Forms Authentication a lot of those questions will be answered for you.
In your Web Config find the line that says authentication="Windows" and then change that to Forms
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" />
</authentication>
MVC 3 will actually give you the Account/LogOn route as part of the MVC 3 template project (check your models and see if you have one called AccountModel).
Then you just add Authorization to deny all users to your site:
<authorization>
<deny users="?"/>
</authorization>
by default this will send any person coming to your site off to your login.
So after you have validated that there login credentials are correct you set the AuthCookie the same as ASP.NET:
FormsAuthentication.SetAuthCookie(userName, false);
Form this you can the redirect to where ever you want.
to redirect back to where you came from use:
FormsAuthentication.RedirectFromLoginPage(userName, false);
Not forgetting the other useful statement of:
FormsAuthentication.SignOut();
Without Authentication the site wont let you access anywhere until you are logged in, so the CSS will stop working.
The locations I have added to make sure this doesnt happen are as follows:
<location path="Content">
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
<location path="Scripts">
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
In asp.net it is a ?returnUrl=...
(1) Make sure you have something like
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
in your root web.config.
(2) In your Controller you want to protect, add [Authorize] attribute above it.
Please create new project and select the Internet Application template rather than Empty one and you will get sample of the simple login process as well as changing password.
Note: Please read this as well: http://www.asp.net/mvc/tutorials/preventing-open-redirection-attacks
The sample shows after logging in process, it make sure the returnUrl is a local url by the Url.IsLocalUrl() helper to protect from Open Redirection Attack.
Update:
The best way is to implement your own custom login process after you really know the standard process for example instead of using the URL to track where the user come from, you can set a new cookie to store the returnUrl with httponly cookie and delete it just before redirect to previous page.
Another common practice is to use roles. You may specific a directory/controller for specific group of user called Role by adding the permitted role like this as an attribute above the controller:
[Authorize(Roles = "Admin")]
See this visual studio administration tool to create sample users and roles with built-in web interface.
You may also want to use sitemap to arrange your pages and menu link with show/hide menu based on current user role. Use this mvcsitemap to add security trimming features in ASP.NET MVC sitemap.
In some cases there happens to be a custom authentication instead of standard forms based (common case for enterprise level applications).
In this case I would recommend manually managing returnUrl parameter in the querystring. Login page reads this URL and redirects back after successful authentication.

Categories