Why Use ADO.NET in the Security Framework?
Published on: 2018-07-24
I'm sure many people find the use of ADO.NET, rather than Entity Framework, as the technology to use for the data access logic in the SQL Server plugins for my security framework as rather odd. After all, Microsoft chose Entity Framework as its database connection mechanism in the default web template, so shouldn't it be good enough for the security framework? While I think that the use of object-relational mappers for general development work is fine, it wasn't the right choice here for reasons I'll outline below:
Reason #1: Performance
I'm not generally a fan of pre-optimizing code for performance. In most cases, code probably ought to be written for readability and maintainability first, and only be optimized for performance when issues arise. Using slower-executing code that speeds up developer productivity is generally a good trade-off. (And there should be no doubt that optimized ADO.NET is faster than Entity Framework, since Entity Framework uses ADO.NET under the covers, and any performance bottleneck in ADO.NET exists in EF, but the reverse is not true.) In the framework's case, though, we're adding extra processing on top of ASP.NET. This processing is necessary to keep you and your users safer from hackers, but it does slow down the system slightly. To minimize the difference in execution speed, I've chosen to speed up the database access logic where I can in order to minimize the performance differences between the default template and adding extra security.
Reason #2: Security
To see why security is an issue, we first need to delve into a concept called "defense in depth". The idea behind defense in depth is that you don't just harden (add security for) your entry points from hackers – you harden the system however you can so if a hacker does get through your first line of defenses, the damage he/she can do is minimized. One example of this is cross-site scripting (XSS) prevention. In a nutshell, one XSS attack occurs when the attacker can save a malicious JavaScript script to your database, then have it execute when shown on the screen, stealing information, credentials, etc. We should certainly prevent users from saving scripts to the database, but we also prevent scripts from being run on the web page in case our first line of defense, preventing users from saving scripts, is bypassed in some way.
This is important in this context because code-first Entity Framework (as of this writing, the only flavor of Entity Framework available in .NET Core) creates database objects on behalf of the developer. While this is convenient, having the process which accesses your database have enough permissions to create objects is a terrible idea from a security standpoint. The permissions the database access process has should be the minimum permissions necessary in order to access the minimum amount of data necessary to work. Any more permissions just gives a hacker who has penetrated your first line of defenses that much more ability to wreak havoc on your system.
Final Notes
Because of these limitations, I do not foresee including code-first Entity Framework support in the security framework, nor do I plan on using code-first Entity Framework for apps that I build for customers, at least until I have been able to implement fixes for its security flaws. (You may, of course, use code-first Entity Framework for all of your data needs outside of the framework if you choose to do so. I'd recommend separating your data logic for your application from the authentication code anyway because it keeps these calls separate, making them easier to maintain and secure.) You shouldn't notice a difference because all of the data access logic is written for you, but if you still wish to use code-first EF as your data access for this framework, please contact me and I can help.