MVC4 Windows Authentication Redirect to Account/Login - asp.net-mvc-4

I am setting up Windows Authentication in an MVC 4 application using Visual Studio 2013 and using the IIS Express Development Server. However, I get redirected to /Account/Login (as if I were using forms authentication).
I have no reference to WebMatrix in my bin folder (or anywhere) as described here: ASP.NET MVC3 and Windows Auth on IIS keeps redirecting to /Account/Login.
I have added these entries to appSettings in the web.config as suggested by this post:
MVC5 Redirects to Login.aspx when using Windows Authentication
<add key="autoFormsAuthentication" value="false" />
<add key="enableSimpleMembership" value="false"/>
Here is what I have done so far:
Added windows authentication to system.web.
<authentication mode="Windows"/>
Added the [Authorize] attribute to my controller. I have also tried using the authorization tag in the web.config instead of the attribute on the controller (deny users="?"). The results are the same.
For the Development Server settings in my project I changed these settings:
Anonymous Authentication = Disabled
Windows Authentication = Enabled
I can find no reference to FormsAuthentication. I can't figure out why it still redirects to a non-existent login page.

When the project was created it may have been done using a template that added Startup.Auth in the App_Start folder in your project. (The default template uses Individual User Accounts if you did not change it to windows authentication as the Authentication method in the create new ASP.Net Project dialog)
Try commenting out these lines if they are present
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
Or if you have not added anything to this file you could remove it completely and the call to it
ConfigureAuth(app);
found in the startup.cs in the root of the project
Now most of the account controller is no good to use if this case so be prepared to clean that up also.
This line is important and correct in the web config
<authentication mode="Windows"/>
these lines are probably not directly related to the issue and can be removed
<add key="autoFormsAuthentication" value="false" />
<add key="enableSimpleMembership" value="false"/>
The other development settings are also correct.

Related

My Entity Framework Core API works fine locally, but fails with a 405 error in production

I have a .NetCore 3.1 API project that uses Entity Framework.
It is working perfectly when I run it locally from Visual Studio.
However, after publishing to a production IIS 8.5 server, I get the following errors when I try to hit an API that uses PUT on the production server.
xhr.js:178 PUT https://nationalparks.xyz.gov/api/plants/91 405 (Method
Not Allowed)
My controller begins like this:
[HttpPut("{id}")]
public async Task<IActionResult> PutPlant(long id, [FromBody] Plant plant)
{
...
}
And client-side looks like this:
await axios({
method: "PUT",
url: "api/plants/" + plant.id,
data: JSON.stringify(plant),
headers: { 'Content-Type': 'application/json; charset=utf-8' }
});
Honestly I'm stumped...I'm not sure why it's doing that.
I've seen a few posts saying to modify the web.config, but my app uses appsettings.json, not a web.config.
Any ideas?
Thanks!
The reason behind the issue is the WebDAV module intercepted the request. to resolve the issue you could follow the below workaround.
1)Remove WebDAV from your system:
open control panel-> “Turn Windows Features On or Off”->un-ticking the WebDAV publishing checkbox.
or
2)Add below code in your web.config file:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>
Please remember that after doing these changes you can nit use the WebDAV module in iis.
dotnet core applications do use web.config when running under IIS. You will notice that the publish command makes a web.config file that tells IIS which DLL to run for your application.
I think I had the same issue a while back. I fixed it by adding lines to web.config to remove the WebDAV modules. See this answer for more detail:
https://stackoverflow.com/a/12443578/65432

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")
});

BetterCMS with MVC4 Simple membership provider

I've set up BetterCMS in my MVC4 app. and it seems like it's working except I can't figure out how to configure it to use Simple Membership Provider that comes with MVC4 internet app.
http://www.devbridge.com/articles/better-cms-for-developers
please help!. thanks
EDIT: I've created my MVC4 app using Internet Template which comes with Simple Membership Provider already configured and working. I would like to have those members I've "registered" as BetterCMS users.
If you want to use Better CMS, use BetterCms.Module.Users module from NuGet with it's role provider, membership provider and UI for managing users. How to setup users module, you can read in BetterCMS wiki pages on Github
But if you still wish to use Better CMS with Simple Membership Provider, follow steps below. That's what I've done and it works fine for me.
Create an MVC 4 solution and select Internet template
Run the application and create a user
Install BetterCMS by following steps, explained in Better CMS github wiki, section "Project Setup".
Do not forget to remove default routes registration (routes.MapRoute(name: "Default" ....) from RouteConfig class.
Register routes below in the RouteConfig class. After that MVC home page can be reached by URL /home/:
routes.MapRoute("mvc-account-controller", "account/{action}/{id}", new
{
area = string.Empty,
controller = "Account",
action = "Login",
id = UrlParameter.Optional
});
routes.MapRoute("mvc-home-controller", "home/{action}/{id}", new
{
area = string.Empty,
controller = "Home",
action = "Index",
id = UrlParameter.Optional
});
Add role provider and membership provider to web.config (solution found here):
<roleManager enabled="true" defaultProvider="simple">
<providers>
<clear/>
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
<membership defaultProvider="simple">
<providers>
<clear/>
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"/>
</providers>
</membership>
Add LazyInitializer to global.asax as explained here
Remove [InitializeSimpleMembership] attribute from AccountController, because database connection is already initialized. Also, SMP2.Filters.InitializeSimpleMembershipAttribute class can also be deleted.
Create an admin role and assign it for user (it can be done using ASP.NET Configuration or directly in the database). For example, create role with name "Role1".
There are two ways to set up administrator roles for the user (you can read more in the Better CMS Github Wiki, topic "CMS configuration"):
Set your created role as full access role (cms.config, security section's fullAccessRoles attribute set to fullAccessRoles="Role1" )
Add roles mappings in the cms.config's security section:
<customRoles>
<add permission="BcmsEditContent" roles="Role1" />
<add permission="BcmsPublishContent" roles="Role1" />
<add permission="BcmsDeleteContent" roles="Role1" />
<add permission="BcmsAdministration" roles="Role1" />
</customRoles>
Run application. Go to url /account/login and log-in using admininstrator account, which was created in the 2nd step. Then go back to any CMS page, for example, root page (/).
Here you go, you're connected as administrator and CMS sidebar is availabe for web site editing.

Running WebApi alongside MVC project in Azure

I have a solution with an MVC project and also a separate Web Api project. I have been working on the the MVC portion and have had it hosted as a web role in a cloud service project.
Now I need to build on the Web Api. Running the solution as is in the azure emulator I'm unable to hit my Web Api controller, I get a 404 Not Found.
What steps do I need to take after creating the WebApi project in the solution in order to enable my MVC project alongside it to hit the Api controller using a jQuery ajax call (from the MVC project)?
Note: The portion of the application that will be consuming the Api is in a subdomain (ex "consumingapp.myapplication.com/api/Values". I don't know if that makes any difference.
Ok here are the steps to run MVC and WebApi side by side in Azure under a single web role:
Add only the MVC project as a Web Role in the Cloud Service project.
Open ServiceDefinition.csdef an configure as follows:
<Sites>
<Site name="Web" physicalDirectory="..\..\..\Application.Web">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
<Site name="Web.Api" physicalDirectory="..\..\..\Application.Web.Api">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="api.myapplication.com"/>
</Bindings>
</Site>
</Sites>
Note:
The physical directory is relative to the definition file that is deployed to CloudProject\bin\release so you need to back track 3 nodes to get to the solution folder. Also I had some trouble with this trying to run the project it would automatically switch the physicalDirectory back to a bad path. To fix that I right clicked the cloud project > Project Dependencies > make sure both projects are checked off. Also make sure to save and close all instances of the text editor for the definition file then Rebuild and finally Run. Seems like some kind of bug that was driving me nuts and eventually disappeared.
Configure your host files to allow for local testing using the emulator:
127.0.0.1 myapplication.com api.myapplication.com
To use this .NET cors implementation run the following Nuget command on your WebApi project:
Install-Package Thinktecture.IdentityModel
Add the following class (taken from the post) to your WebApi project:
public static class CorsConfig
{
public static void RegisterCors(HttpConfiguration httpConfiguration)
{
WebApiCorsConfiguration corsConfig = new WebApiCorsConfiguration();
corsConfig.RegisterGlobal(httpConfiguration);
corsConfig
.ForResources("Values") //Controller nae
.ForOrigins("http://myapplication.com", "myapplication.com:81")
.AllowAll();
}
}
Call RegisterCors() from Application_Start()
Make sure you Web.config in the WebApi project has OPTIONS verb for the ExtensionlessUrlHandler:
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
Make cross-origin request to hit your api controller:
$.ajax({ url: "http://api.myapplication.com/api/Values", ... })
And Viola!
Hope that helps others

how to use a business identity provider (e.g. ADFS2)

I am running Win 7, IIS 7.0, VS2012
I have created asp.mvc4 web app
I have ADFS2.0 on a separate VM
Using the Identity and Access tools in VS 2012
I select use a business identity provider (e.g.ADFS2) and type the url to the STS metadata document.
https://server.local/federationmetadata/2007-06/federationmetadata.xml
edited the web config
<system.web>
...
<httpModules>
...
<remove name="FormsAuthentication" />
</httpModules>
</system.web>
and this
<system.webServer>
...
<modules>
...
<remove name="FormsAuthentication" />
</modules>
</system.webServer>
Also have checked that Windows Authentication was disabled for the project
The website redirects to a url like this http:// localhost /WebSite/login.aspx?ReturnUrl=%2fWebSite%2f which has a 'The resource cannot be found' error.
What else do I have to fiddle with to make this work?
The Microsoft doco is lightweight http://blogs.msdn.com/b/vbertocci/archive/2012/03/15/windows-identity-foundation-tools-for-visual-studio-11-part-iii-connecting-with-a-business-sts-e-g-adfs2.aspx
I already have had similar problems with the local development STS MS Identity and Access Tool MVC 4
Ok this has taken me days to work out but these were the things I did to get it running. There is much more to do.
Prerequisites:
An ADFS 2.0 service running somewhere on your domain.
IIS 7 with a self signed certificate or a certificate that you can use across your domain.
Visual Studio 2012 with the Identity and Access (version 1.0.2) Extension installed.
A MVC4 web application set to run on IIS.
Ensure that Self Signed Certificate is added to the site so you can access it via https.
You may have to tweak the firewall settings of you machines to allow access to your ADFS 2.0 service.
On the Development Workstation
In your MVC4 Project
Open up the Identity and Access Dialog by right-clicking your web project.
Choose Use a business identity provider (e.g. ADFS2)
Enter the path to the STS metadata document e.g. https://{PATH TO ADFS SERVER}/FederationMetadata/2007-06/FederationMetadata.xml
Enter the realm for your application e.g. https://{WEB APPLICATION URL}/
The trailing slash makes a difference.
Exit the dialog by accepting these changes.
Add the following code to your project
using System;
using System.IdentityModel.Services;
namespace NAMESPACE
{
public class FixedWsFederationAuthenticationModule : WSFederationAuthenticationModule
{
public override void RedirectToIdentityProvider(string uniqueId, string returnUrl, bool persist)
{
//This corrects WIF error ID3206 "A SignInResponse message may only redirect within the current web application:"
//First Check if the request url doesn't end with a "/"
if (!returnUrl.EndsWith("/"))
{
//Compare if Request Url +"/" is equal to the Realm, so only root access is corrected
//https://localhost/AppName plus "/" is equal to https://localhost/AppName/
//This is to avoid MVC urls
if (String.Compare(System.Web.HttpContext.Current.Request.Url.AbsoluteUri + "/", base.Realm, StringComparison.InvariantCultureIgnoreCase) == 0)
{
//Add the trailing slash
returnUrl += "/";
}
}
base.RedirectToIdentityProvider(uniqueId, returnUrl, persist);
}
}
}
On the ADFS 2.0 Server
If you used a self signed certificate navigate to your web application https://{WEB APPLICATION URL}/ and change the zone to trusted site.
In the address bar of the browser you should be able to right click on the certificate and install (you can only install Certificates from trusted sites) The certificate needs to be installed under Trusted Root Authorities -> Registry,
Open the ADFS Console, add Relying Party Trusts, with Federated Metadata address https://{WEB APPLICATION URL}/FederationMetadata/2007-06/FederationMetadata.xml
Add some custom rules
MVC4 needs these rules in order to make a usable ClaimsPrincipal
Add a pass-through rule on the Name property.
And these 2 custom rules
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Value = "true");
=> issue(Type = "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", Value = "true");