IIS Virtual Directory/Application & Forms authentication - authentication

I've setup and deployed a simple forms authentication website with membership using .NET 4.
I've created a virtual directory (now converted to "Application") in IIS7 and setup the web.config file in the virtual directory as follows:
<configuration>
<system.web>
<authorization>
<deny users="?">
</authorization>
</system.web>
<system.webServer>
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>
Great! I browse to the virtual directory: ../mydomain/books/
and I'm automatically redirected to the login page specified by web.config in my root directory and the url path is placed as follows:
../Account/Login.aspx?ReturnUrl=%2fbooks
At this point, I login succesfully, but I am not redirected anywhere, and when I manually return to the directory, ../books, I'm sent back to the login page, where I'm already logged in?
So I'm confused about what my problem is! I should be successfully authenticated, and than redirected back to the directory, or at the very least be able to view it manually after I log in right?

Since I had to solve this myself, I thought I may as well post it for others in case their search brings them here.
This is everything you'll need to use Forms Authentication, allow your formatting to be exposed to anonymous users, pass credentials between an existing .Net (.aspx) web site and an MVC web application and redirect to a given url after login.
Use whatever pieces you are looking for.
Make sure your Virtual Directory/Virtual Application path for your .Net web application (.aspx) is outside of the Views directory. Also make sure you set up your Virtual Directory/Application in IIS.
I used Entity Framework and Identity with a SQLServer database to validate my users.
Your Virtual Application/Directory .Net (.aspx) web.config file needs to contain this:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<!-- other stuff -->
<system.web>
<authentication mode="Forms">
<forms
loginUrl="login.aspx"
name=".AUTHCOOKIE"
protection="All"
path="/"
domain="your_domain.com"
enableCrossAppRedirects="true"
timeout="60">
</forms>
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
<machineKey
validationKey="your validation key"
decryptionKey="your decryption key"
validation="SHA1"
decryption="AES"
/>
<!-- other stuff -->
</system.web>
<location path="/path/to/your/site.css">
<system.web>
<authorization>
<allow users="?"></allow>
</authorization>
</system.web>
</location>
<!-- other stuff -->
</configuration>
Then, in the code behind your login.aspx page you'll need something like this:
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
string username = Login1.UserName;
string pwd = Login1.Password;
/* do your authentication here
connect to user store
get user identity
validate your user
etc
*/
if (user != null)
{
FormsAuthentication.SetAuthCookie(username, Login1.RememberMeSet);
System.Web.HttpCookie MyCookie = System.Web.Security.FormsAuthentication.GetAuthCookie(User.Identity.Name.ToString(), false);
MyCookie.Domain = "your_domain.com";
Response.AppendCookie(MyCookie);
Response.Redirect("~/path/to/your/index.aspx");
}
else
{
StatusText.Text = "Invalid username or password.";
LoginStatus.Visible = true;
}
}
Now, in your MVC applications web.config file add this:
<configuration>
<!-- other stuff -->
<system.web>
<authentication mode="Forms">
<forms
loginUrl="Account/Login"
name=".AUTHCOOKIE"
protection="All"
path="/"
domain="your_domain.com"
enableCrossAppRedirects="true"
timeout="30"/>
</authentication>
<authorization>
<deny users="?"/>
<allow users="*"/>
</authorization>
<machineKey
validationKey="your validation key"
decryptionKey="your decryption key"
validation="SHA1"
decryption="AES"
/>
<!-- other stuff -->
</system.web>
<location path="/path/to/your/site.css">
<system.web>
<authorization>
<allow users="?"></allow>
</authorization>
</system.web>
</location>
<!-- other stuff -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthenticationModule"/>
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule"/>
<remove name="UrlAuthorization"/>
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule"/>
</modules>
</system.webServer>
<!-- other stuff -->
</configuration>
In your MVC AccountController Login method should look something like this:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
/* do your authentication here
connect to user store
get user identity
validate your user
etc
*/
if (user != null)
{
await SignInAsync(user, model.RememberMe);
FormsAuthentication.SetAuthCookie(model.Email, model.RememberMe);
System.Web.HttpCookie MyCookie = System.Web.Security.FormsAuthentication.GetAuthCookie(User.Identity.Name.ToString(), false);
MyCookie.Domain = "your_domain.com";
Response.AppendCookie(MyCookie);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Finally, your MVC AccountController log off method is this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
FormsAuthentication.SignOut();
return RedirectToAction("Login", "Account");
}

You need to add code to redirect to the "ReturnUrl" URL noted in the query string from within your Login page after you login.

Related

Remove response Server header on Azure Web App from the first redirect request to HTTPS

I’m trying to remove the response Server header from an Azure Web App ( with an ASP Net core application )
After many tries of changing the web.config and removing the header in app code using a middleware, Microsoft doesn’t give up and set the response header to Server: Microsoft-IIS/10.0 :)
The problem appears only when I’m trying to access the server on http (not https). Response code from the server is 301, and this is the only response that has the Server header.
Checking the logs I was not able to find any request to http://, and perhaps this is why I’m not able to remove header, because the request is not process in my application code.
A solution that I’m thinking is to disable the azure HTTPS only and do the redirect to https in my code (I tested and is working - server header is removed)
Is there another workaround without disabling the HTTPS only option?
Here is what I tried
Startup.cs
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
context.Response.Headers.Add("server", string.Empty)
}
app.UseHttpsRedirection();
}
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<httpRuntime enableVersionHeader="false" />
<!-- Removes ASP.NET version header. -->
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Server" />
<remove name="X-Powered-By" />
</customHeaders>
<redirectHeaders>
<clear />
</redirectHeaders>
</httpProtocol>
<security>
<requestFiltering removeServerHeader="true" />
<!-- Removes Server header in IIS10 or later and also in Azure Web Apps -->
</security>
<rewrite>
<outboundRules>
<rule name="Change Server Header"> <!-- if you're not removing it completely -->
<match serverVariable="RESPONSE_Server" pattern=".+" />
<action type="Rewrite" value="Unknown" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
UPDATE
When the URL of http:// is requested, IIS will process it, this time without code. So we can't control it by the code, we can only set it on the server, such as some scripts or tools. But on Azure, we have no way to directly operate as a physical server, so after exploration, I suggest that Front Door can be used to deal with this problem. Hiding server information through proxy should be a better way.
After my test, the server information is hidden, you can refer to this document . We can see from the picture that there is no 301 redirect request, and no server information in other requests.
PREVIOUS
You need to modify Global.asax.cs and Web.config file in your program.
In Global.asax.cs.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
MvcHandler.DisableMvcResponseHeader = true;
PreSendRequestHeaders += Application_PreSendRequestHeaders;
}
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
//HttpContext.Current.Response.Headers.Remove("Server");
HttpContext.Current.Response.Headers.Set("Server","N/A");
}
}
And In Web.config.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" >
</modules>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
</system.webServer>
Then u can deploy your app. After the above code modification, access to the interface or static resources can see that the server information is modified, of course, it can also be deleted by Remove.
You also can handle special event by http status code.
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
//HttpContext.Current.Response.Headers.Remove("Server");
int StatusCode= HttpContext.Current.Response.StatusCode;
// handle like http status code 301
HttpContext.Current.Response.Headers.Set("Server","N/A");
}

Is Active Directory authentication used?

I've inherited MVC4 application. It looks like Windows Authentication is used, but I also was told that "Active Directory Authentication" is used for some permissions. I do not see anything in web.config about Active Directory.
In web.config:
<authentication mode="Windows" />
<roleManager defaultProvider="DefaultRoleProvider">
<providers>
<add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=21bf1234ad634e53" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</roleManager>
In Controller:
[Authorize(Roles = #"ABCD\EFG"), HandleError(ExceptionType = typeof(UnauthorizedAccessException), View = "UnauthorizedUser", Order = 1)]
public class HomeController : Controller
{ .............
}
public ActionResult MyAction()
{
if (!User.IsInRole(#"ABCD\EFG"))
{
// some code
}
//.............
}
Is "Active Directory Authentication" used in this application ?
Thank you
The windows authentication will indeed integrate with Active Directory as long as the application server is on the domain your users are registered in.
The below line in your config file enables such functionality.
<authentication mode="Windows" />
This post might help you get further:
Configure ASP.NET MVC for authentication against AD

Identity.Name is null

My MVC application,
Decorated controller with
[AuthorizedRoles(Roles = "Manager")]
and I am trying to get the requested user name using HttpContextBase
public class AuthorizedRoles : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
httpContext.User.Identity.Name
Why Identity.Name is null ?
Web.config looks like
<authentication mode="Windows" />
<authorization>
<allow users="*"/>
</authorization>
Please help to get the request User ..
Okay this is what you need to do!
I don't know what to set in the web.config - but changing these options makes it work. to get this screen select you project and press 'F4'
EDIT: I imagine you will need to configure this in IIS when you host the site as well.
This might help in the web.config
<system.webServer>
....
<security>
<authentication >
<anonymousAuthentication enabled="false"/>
<windowsAuthentication enabled="true"/>
</authentication>
</security>
</system.webServer>

User can successfully log in but log in page shows up instead of redirecting

I have a moved a project from asp.net mvc 2 to asp.net 4 and after a bit of fixing everything seemed to work.
EXCEPT for the parts of the app where you have to authorize. Without authorizing it is possible to view non-authorize pages but as soon as you try to log-in everything goes
bananas. When you log-in you get logged in (you see your name in the log-in partial) but not redirected and prompted to log-in again and you can not reach parts of the
app that is for non-authorized users. Everything works on localhost but not at deployed site.
At first i thought there was a problem with my machinekey and app-pool recykling, so i added one. Still same problem.
I know that MVC uses websecurity instead of membership but i've read that an Membership solution can exist in a mvc 4 project, and i would be glad to use my custom membershipprovider and roleprovider and save some time if it is possible.
Controller:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, true);
FormsAuthentication.SetAuthCookie(model.UserName, true);
var role = userRepo.usersInRoles.First(x => x.userMail == model.UserName);
if (role.roleName == "Business")
return RedirectToAction("Start", "Business");
if (role.roleName == "Admin")
return RedirectToAction("Index", "Admin");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
return View(model);
}
Config settings for Membership & Role
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<membership defaultProvider="AccountMembershipProvider">
<providers>
<clear />
<add name="AccountMembershipProvider" type="MyApp.UI.Infrastructure.AccountMembershipProvider" applicationName="/" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="RoleMembershipProvider">
<providers>
<clear />
<add name="RoleMembershipProvider" type="MyApp.UI.Infrastructure.RoleMembershipProvider" />

404 errors for PUT and DELETE requests on deployed WCF RESTful Service

I have deployed an MVC3 and WCF web service as a single application. Both work as expected. GET and POST requests work perfectly, but the PUT and DELETE requests return 404 errors. These work fine locally. Initially it was requesting a username/password for PUT/DELETE requests.
Here is my WebServer config from my web.config file
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAVModule" />
</handlers>
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" users="*"
verbs="GET,HEAD,POST,DEBUG,PUT,DELETE" />
</authorization>
</security>
</system.webServer>
Here are my PUT and DELETE methods:
[OperationContract]
[WebInvoke(UriTemplate = "{id}", Method = "PUT")]
public MyResource Put(MyResource updatedResource, int id)
{
MyResource existingResource = Database.GetResourceById(id);
existingResource.Name = updatedResource.Name;
Database.SaveResource(existingResource);
return existingResource;
}
[OperationContract]
[WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
public MyResource Delete(int id)
{
MyResource sampleResource = Database.DeleteResourceById(id);
return sampleResource;
}
My set up:
.NET 4.0
MVC3
IIS 7.0
Note: I am on a shared hosting plan, therefore do not have direct access to IIS7.0 a so I need to make changes via the web.config file.
Enable Tracing on your service and see why you get a 404 error when you try for a PUT or DELETE action.