Where are the Authentication views in AspNet Core App?

I am struggling with Visual Studio for Mac. I have been a Visual Studio user since it came in multiple CDs in a box. Visual Studio has been improved a lot, I like it more now than I did before. But there is a problem, the VS version for the Mac is a completely different product. I am both a Mac and PC user, I like both operating systems, Windows and Mac OS. However, I have been trying to use my personal laptop (MacBook Pro M1) for my personal software projects, and a lot of them were initially created with VS for Windows.

Visual Studio for Mac lacks some important things I use in my projects, for example, SQL Server Data Tools (SSDT) projects. I know that this is because we cannot install SQL in a Mac, and also know that there are alternatives to SSDT, like Azure Data Studio… but guess what? It’s not compatible with the ARM architecture which is what Apple’s new chip (M1) uses, and that’s the laptop I have ūüėē.

New Web project using Visual Studio for Mac

Anyways, that’s a topic for another post, this is about finding the Authentication views in an ASP.NET Core app. Since I couldn’t use this MacBook to continue working on my existing projects, I decided to use it only for new ones. That should be fine. So I have an idea for a book-sharing app, and I wanted to use VS for Mac to create this web app. I started with one of the templates and in less than a minute I had a working web app on my laptop. Next, I decided to scaffold the Authentication stuff to get authentication features and allow users to do stuff like the following:

  • Register
  • Login/Logout
  • Forgot Password
  • Reset Password
  • Confirm Email
  • Etc.

Scaffolding Identity features

I ran the following commands in my Terminal and on my project’s root directory to add the ability to scaffold the identity stuff. You might not need to do this if you have already installed the aspnet codegenerator:

dotnet tool install -g dotnet-aspnet-codegenerator

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Identity.UI
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools

dotnet aspnet-codegenerator identity -h

Where are my Identity views?

After this, I ran the following command to add the Authentication features to my project. The following command needs to be run inside your project’s directory:

dotnet aspnet-codegenerator identity -dc ReadMoreBooks.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout"

After doing this, I didn’t see many changes in my solution, but when I ran my application again, I noticed I had the option to register, login, and logout. I registered a test user, and everything worked fine. Until I wanted to edit the page where a user confirms registration and also the page to reset the password. I was expecting to see ConfirmEmail and ResetPassword views under Areas > Identity > Pages > Account – but they weren’t there, only Register, Login, and Logout.

Where are they? After doing some research and spending a good amount of time searching for them in my solution, I found out that Microsoft hid these views to make projects smaller and more organized. This is the blog post where they announced that and that I clearly missed: https://devblogs.microsoft.com/dotnet/aspnetcore-2-1-identity-ui/

So, it turns out that by using the command line to scaffold these views I was already halfway from where I needed to be. What I mean by that is, by using the command tool (I think this is available through the UI but only in VS for Windows), all I had to do was either not specify which views I wanted to scaffold or specify all the views I wanted to include in my project so I could customize them.

The first command is what I ran initially, which helped create the Register, Login, and Logout views, and while everything else within the Authentication was available, the actual files were hidden.

dotnet aspnet-codegenerator identity -dc ReadMoreBooks.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout"

Bringing back the Identity views into my project

So what I ran after was the following command, which added the views I wanted to my project so I could access them and customize them as much as I needed.

dotnet aspnet-codegenerator identity -dc ReadMoreBooks.Data.ApplicationDbContext --files "Account.ConfirmEmail;Account.ForgotPassword;Account.ForgotPasswordConfirmation;Account.Lockout;Account.LoginWith2fa;Account.ResetPassword;Account.ResetPasswordConfirmation"

That’s it! As soon as the command above was executed, all the authentication-related views appeared in my solution, just like in the old times. Perfect.

Now, I learned that I also have the option to run the same command without specifying the –files command, which will then add all of the available views related to Authentication to your project.

dotnet aspnet-codegenerator identity -dc ReadMoreBooks.Data.ApplicationDbContext

Conclusion and suggestions

So there you have it folks, a feature by Microsoft was a bug for me, at least for a while, until I understood what was happening, and then I learned how to navigate through the changes and get what I wanted.

If you want to learn more about the scaffolding options and how you can use them in your projects, check out this page from Microsoft: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-6.0&tabs=netcore-cli&viewFallbackFrom=aspnetcore-2.1

The moral of the story, read the documentation, keep up to date so you are aware of what’s changing and why, and maybe you’ll save some headaches and be more proficient with your coding. Hope this is useful. Cheers!

How to add simple logging to your Web App using Elmah

Logging is a crucial part of any application. Logging can be used to track events, identify code issues, security holes, etc. In this blog post, I’ll describe how to add logging to your ASP.NET web application using an open source logging framework called Elmah.

Elmah has been around for a while, it became very popular for its pluggable framework. Elmah can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.

Another common open source logging framework for .NET is a port of the excellent Apache log4j framework to the Microsoft .NET runtime, log4net. However, in this blog, I’ll focus on how to enable logging for your ASP.NET web application using Elmah.

Install Elmah

Get the latest Elmah version by typing the following into your Package Manager Console.

PM> Install-Package elmah.sqlserver

In this example, I am using the Elmah SQL package that comes with the files and configuration needed to log errors in a SQL table. After running the command above, you’ll see a new directory, App_Readme with two files in it.

solution1 Continue reading →

Error 0x80131902: Failed to create the managed bootstrapper application.

This error message has been giving me headaches for a while, I have seen it happen in different Windows computers when trying to install a Visual Studio update or a new version of Visual Studio. If you Google for the string “Error 0x80131902: Failed to create the managed bootstrapper application.” you’ll find some sites and forums where the following advice and tips are given:

The error in the log, 0x80131902, means that the .NET Framework could not be loaded (more specifically, an AppDomain could not be created).

Do you have at least .NET 3.5 installed/enabled on your machines? You might also connect to Windows Update and make sure you have all required updates installed. There may be some bugs that have been fixed in the .NET Framework.

Another possibility – though not for this specific error but in general – is that your graphics drivers our out of date or not appropriate for your card (mentioned to @TobiasUlm below in another thread). Setup uses WPF and sometimes bad graphics drivers can cause issues (happened with VS itself for some users).

Visit your graphics card’s manufacturer web site and make sure you have the newest driver available for your card and, on Windows 7, that you have the latest DirectX runtime installed. See http://support.microsoft.com/kb/179113 for more information.

– Heath @ http://blogs.msdn.com/heaths; Visual Studio Professional Deployment

Also…

As you can install VS11 with the same ISO successfully on other machines, I think your VS11 ISO should be fine. And please follow the steps below to see if it helps you:

TemporarilyTurn off your anti-virus/antispyware software during installation;
Install the latest Windows updates from the Windows Update site: http://update.DataZX.CN;
Complete or dismiss Windows Update before installation. (And don’t forget to turn it on
later);
Clean your %temp% folder (Start Menu >>Run >> Type “%temp% >> OK);
Then run the setup with Administrator privilege: right-click the installer -> Run as administrator.
Thanks.

Vicky Song [MSFT]
MSDN Community Support

And…

Do you also install VS11 Developer Preview on that Windows7 machine? If so, I am afraid you need to first uninstall the VS11 DP and then install the VS11 Beta again.

In addition, please try to uninstall VS11 Beta completely from your machine and then try re-install it to see if you get the same result. And for the .NET application related issues, I think can consider reinstall .NET Framework 4.5 again. You can find it here:

http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27541

If you still get the same result, please offer me the complete installation log files you get.

Of course I tried all of those suggestions but none of them worked for me. Every time I tried to install a VS update or a new version of VS – this is the entire log showing me the errors, the error messages were exactly the same for both updating or trying to install a new version of VS:

…..

[0898:1304][2014-04-11T09:08:22]: Loading managed bootstrapper application.
[0898:1304][2014-04-11T09:08:22]: Error 0x80131902: Failed to create the managed bootstrapper application.
[0898:1304][2014-04-11T09:08:22]: Error 0x80131902: Failed to create UX.
[0898:1304][2014-04-11T09:08:22]: Error 0x80131902: Failed to load UX.
[0898:1304][2014-04-11T09:08:22]: Error 0x80131902: Failed while running

…..

[0898:1304][2014-04-11T09:08:22]: Error 0x80131902: Failed to run per-user mode.
[0898:1304][2014-04-11T09:08:22]: Exit code: 0x80131902, restarting: No

As you can see the advice is very similar and while this might have helped some people, it did not help me. After looking around extensively and trying different approaches, I did the opposite of what most people suggested and actually turned off the Microsoft .NET Framework 3.5.1 Windows feature located under Programs and Features – Turn Windows features on or off – see screen shot below:


disable 3.5 .NET framework photo

After turning off Microsoft .NET Framework 3.5.1 I tried installing the updates for VS2012 and installing VS2013 and everything worked flawlessly. After the installations completed successfully, I opened back the Windows features on or off menu and enabled the Microsoft .NET Framework 3.5.1 once again.

This is what I got after my simple fix/change and I hope you can get to the following screen too!

VS install successful photo

How to use Active Directory groups to restrict access to controller actions in ASP.NET MVC and make your application even more secure!

It’s been a year and one of the most popular posts in this blog still today is How To: Secure your ASP.NET MVC application and use Active Directory as the Membership Provider. In that post I promised to write about how to use Active Directory groups to restrict access to controller actions to make your application even more secure by consolidating access based in already defined groups in Active Directory (AD). I finally got to it and here it is.

Remember that if you are not already using Active Directory as your membership provider in your application, you need to first follow the steps described in the first post mentioned above.

In a business, the use of Active Directory¬†to organize user and computer accounts is very common. When we create new web applications for that business it is likely that we want to have some access control to certain areas of the application. For example, let’s say that you have a web application that helps accounting and customer support get details about a certain customer such as reports, invoice details, account information, etc… In such application there is a good chance that accounting and customer service employees will have different access to different areas in the application.

The Example

Here is an example of what such a task will look like in the controller of your MVC application:

public ActionResult DeactivateMembership(Membership model)
 {
    // your business logic here
    return View("DeactivateMembership", model);
 }

And here is what is going to look like with an attribute that will only allow users in the customer service group to execute such task

[AuthorizeAD(Groups = Constants.CSgroup)]</strong>
 public ActionResult DeactivateMembership(Membership model)
 {
    // your business logic here
    return View("DeactivateMembership", model);
 }

The custom AuthorizeAD attribute

The custom attribute labeled AuthorizeAD is what makes this happen, below is the declaration of this custom attribute that access Active Directory to determine if an specific user or group within AD has access to a defined controller action:

namespace Application.Filters
{
public class AuthorizeADAttribute : AuthorizeAttribute
{
    public string Groups { get; set; }
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (base.AuthorizeCore(httpContext))
        {
           /* Return true immediately if the authorization is not 
           locked down to any particular AD group */
           if (String.IsNullOrEmpty(Groups))
               return true;

           // Get the AD groups
           var groups = Groups.Split(',').ToList();

           // Verify that the user is in the given AD group (if any)
           var context = new PrincipalContext(
                                 ContextType.Domain, 
                                 "yourdomainname");

           var userPrincipal = UserPrincipal.FindByIdentity(
                                  context,
                                  IdentityType.SamAccountName,
                                  httpContext.User.Identity.Name);

           foreach (var group in groups)
           if (userPrincipal.IsMemberOf(context, 
                IdentityType.Name, 
                group))
               return true;
        }
         return false;
}

protected override void HandleUnauthorizedRequest(
AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
             var result = new ViewResult();
             result.ViewName = "NotAuthorized";
             result.MasterName = "_Layout";
             filterContext.Result = result;
        }
        else
             base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

The code above overrides the AuthorizeCore call which allow us to customize the authorization check so we can use the Active Directory in our domain.

The implementation

To limit access to controller actions you will use the new custom attribute like this:

[AuthorizeAD(Groups = Constants.CSgroup)]

Where Constant.CSGroup is just a constant value I created that translates to the actual name of the AD group. This can also be used to aggregate two or more AD groups as one value if needed. In the class below I set the value of CSgroup to be the name of two different AD groups in my domain, the csr group and csr_leads group:

public static class Constants
    {
        /// <summary>
        /// CS - Customer support and customer support leads
        /// </summary>
        public const string CSgroup = "csr, csr_leads";
}

If you don’t need to do this then you can use the custom attribute by simply providing the name of your AD group, a user name or the name of a Role within your Active Directory:

// Only give access to a group
[AuthorizeAD(Groups = "yourADgroup")]

</strong>
<strong>// Give access to a group and a user
[AuthorizeAD(Groups = "yourADgroup", Users = "someuser")]</strong>
<strong>
// Give access to a Role
[AuthorizeAD(Roles = "Admin")]

That’s it! Hope this is helpful for you and as always, if you have a recommendation, a comment or question please use the comment’s section below.

 

How To: Secure your ASP.NET MVC application and use Active Directory as the Membership Provider

Securing your ASP.NET MVC application should be priority number one every time you start a new web application. Using the attributes Authorize and¬†ValidateAntiForgeryToken in every controller and action is the only way to avoid any security holes. In this post, I’ll show you how to secure your ASP.NET application by implementing the AuthorizeAttribute and¬†ValidateAntiForgeryTokenAttribute classes.

The basics

At the very least, you should add an [Authorize] attribute to every controller or controller Action in case you want some of the controller actions to be accessible by anonymous users. For example, you probably want ALL users to have access to the login and register actions of your web application.

By decorating the HomeController with the Authorize attribute (notice I did not specify any user role), the application will prevent any unauthenticated user from executing any of the actions in this controller.

[Authorize]
public class HomeController : Controller
{
  //...
}

The following is an example of decorating a controller action with the Authorize attribute, you want to do this when you only want to restrict access to some of the actions in a controller instead of all actions.

[Authorize]
public ActionResult Create()
{
  //...
}

Protecting against Cross-site request forgery attack (CSRF or XSRF)

The Authorize attribute offers protection that is sufficient in most cases. However, there is a security hole with this, and thus it opens your web application for a cross-site request forgery attack. For example, after a user logs into your site, the website will issue your browser an authentication token within a cookie. Each subsequent request, the browser sends the cookie back to the site to let the site know that you are authorized to take whatever action you’re making, so far everything is okay.

Here is the problem with only using the Authorize attribute, let’s say that a user is logged in to your website and then they go to a spam site by clicking on a link that points to another site which causes a form post back to your site… this is bad, your browser will send the authentication cookie to your site making it appear as if the request came from your website and initiated by an authenticated user when it really didn’t.

The above scenario is called cross-site request forgery and can be avoided by adding the ValidateAntiForgeryToken attribute available in the .NET framework, this attribute is used to detect whether a server request has been tampered with.

The first step is to add the ValidateAntiForgeryToken attribute to every Post Action as follows:

[HttpPost, Authorize, ValidateAntiForgeryToken]
public ActionResult Create()
{
  //...
}

The next step is to add the HtmlHelper method @Html.AntiForgeryToken() inside the form in your view.

The way the ValidateAntiForgeryToken attribute works is by checking to see that the cookie and hidden form field left by the Html.AntiForgeryToken() HtmlHelper essentially exists and match. If they do not exist or match, it throws an HttpAntiForgeryException shown below:

“A required anti-forgery token was not supplied or was invalid.”

By adding the ValidateAntiForgeryToken to your controller actions, your site will be prepared to prevent CSRF/XSRF attacks.

Implementing Forms Authentication using Active Directory (AD)

Often times you might run¬†across¬†a project where you need to authenticate users of your website using Active Directory credentials, the good news is that you can use the existing “Account” controller to achieve this, only a few modifications are necessary.

When you create a new MVC Web Application project and choose the Internet Application template, the Account controller is added to the project, you can use this controller with AD to authenticate your users. For the Account controller to work with AD we need to remove all Actions but the following:

  • Logon()
  • Logon(LogOnModel model, string returnUrl)
  • LogOff()

Your Account controller should look like the following after you remove the unnecessary Actions such as ChangePassword, Register, etc…

public ActionResult LogOn()
        {
            return View();
        }

        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (Membership.ValidateUser(model.UserName, model.Password))
                {
                    FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/"))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "The user name or password provided is incorrect");
                }
            }

            // if we got this far, something failed, redisplay form
            return View(model);
        }

        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();

            return RedirectToAction("Index", "Home");
        }

After this, go ahead and clean up the AccountModel as well so the only model class left is the LogOnModel:

public class LogOnModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

[Display(Name = "Remember me?")]
public string RememberMe { get; set; }
}

Lastly, add the following to the project’s web.config file:

adconnection

That is all! The first code snippet is the connectionstring to your Active Directory server and the second one is where we specify Active Directory as the application’s default membership provider.

Save your changes, hit Ctrl-F5 and login to your application using your domain/AD account.

Hopefully, this will help you get started to secure your ASP.NET web apps and show you a straightforward way to use ASP.NET’s membership services with Active Directory.

In this post, I show how to use Active Directory groups to restrict access to controller actions and make your application even more secure!