Application Security and Secure Coding: Complete .NET Guide
Application security is the practice of designing, building, and maintaining software systems that resist attacks, protect sensitive data, and enforce user trust. In modern .NET applications, security is not a feature bolted on at the end—it is a foundational design principle that must be embedded from the first line of code. This chapter covers the five essential pillars of .NET application security: authentication (proving who a user is), authorization (controlling what authenticated users can do), defending against industry-standard attack vectors, cryptographic data protection, and secure secrets management. By the end of this series, you will be able to build ASP.NET Core applications that authenticate users securely, enforce fine-grained access controls, resist OWASP Top 10 exploits, encrypt sensitive data, and manage secrets without exposing them in source code.
What You'll Learn
- How to implement authentication with ASP.NET Core Identity and validate user credentials
- How to issue, validate, and refresh tokens using JWT and OAuth 2.0 / OpenID Connect
- How to design and enforce authorization policies for role-based and claims-based access control
- How to defend your application against the most critical real-world vulnerabilities (injection, broken authentication, XSS, insecure deserialization, and more)
- How to encrypt data at rest and in transit, manage cryptographic keys, and handle secrets securely
The Five Series Themes
This chapter is organized into five focused modules that build on each other:
Authentication with ASP.NET Core Identity
ASP.NET Core Identity is the built-in membership system for managing user accounts, passwords, multi-factor authentication, and account lockout. This module teaches you to configure Identity, hash passwords using industry-standard algorithms, validate login credentials, and implement secure password reset workflows. You will understand why storing plain-text passwords is catastrophic and how bcrypt/PBKDF2 protect user accounts even if your database is breached.
JWT, OAuth 2.0, and OpenID Connect
Modern applications often need to authenticate users across multiple services and devices. JSON Web Tokens (JWT) are cryptographically signed tokens that allow stateless authentication. OAuth 2.0 is the industry standard for delegated authorization (letting users grant third-party apps access to their data without sharing passwords). OpenID Connect layers authentication on top of OAuth 2.0. This module explains the difference between each, walks through real token flows, and shows you how to validate tokens and handle token expiration and refresh.
Authorization Policies and Access Control
Even after a user is authenticated, your application must decide what actions they are allowed to perform. Role-based access control (RBAC) groups permissions by job title; claims-based access control is more flexible and attribute-driven. This module covers ASP.NET Core policy-based authorization, how to write custom authorization handlers, and how to avoid the common pitfall of hardcoding permission checks throughout your codebase. You will implement declarative [Authorize] attributes, policy requirements, and conditional access based on user attributes.
Defending Against the OWASP Top 10
The Open Web Application Security Project (OWASP) publishes a ranked list of the ten most critical application security risks, updated every three to four years. These include injection attacks (SQL injection, command injection), broken authentication, sensitive data exposure, XML external entity (XXE) attacks, broken access control, security misconfiguration, cross-site scripting (XSS), insecure deserialization, and using components with known vulnerabilities. This module teaches the root cause of each, demonstrates exploits, and shows concrete .NET code patterns that prevent them. You will learn input validation, parameterized queries, content security policies, and how to stay on top of dependency vulnerabilities.
Cryptography, Secrets, and Data Protection
Encryption ensures that even if an attacker gains access to your database or network traffic, they cannot read sensitive information without the correct cryptographic key. This module covers symmetric encryption (AES), public-key encryption (RSA), hashing and message authentication codes (HMAC), and .NET's Data Protection API (DPAPI) for protecting secrets at rest. You will learn when to encrypt (always for passwords in transit and at rest, always for payment card data), how to generate and manage keys securely, and how to use ASP.NET Core's configuration providers to inject secrets from external vaults instead of committing them to source code. You will implement proper key rotation, understand the difference between encryption and hashing, and avoid common pitfalls like weak RNG or using deprecated algorithms.
Frequently Asked Questions
Why can't I just hash passwords with SHA256?
SHA256 is fast and designed for checksums, not passwords. An attacker with access to your password hash can compute billions of SHA256 hashes per second using GPUs and try all common passwords. Password hashing functions like bcrypt and Argon2 are intentionally slow and memory-intensive, making brute force attacks impractical. ASP.NET Core Identity uses PBKDF2 by default and supports pluggable hashers; you can upgrade to bcrypt with a NuGet package.
When should I use OAuth 2.0 versus JWT?
OAuth 2.0 is an authorization protocol that defines how users grant apps access to their data and how tokens are issued. JWT is a token format. They are not mutually exclusive; OAuth 2.0 flows often issue JWTs. Use OAuth 2.0 when you need to delegate authorization (user logs in via Google, GitHub, or Azure AD) or when you have multiple independent services. Use JWT for stateless authentication in microservices and single-page applications where you want to avoid server-side session storage.
How do I prevent SQL injection in my .NET code?
Never concatenate user input into SQL queries. Always use parameterized queries (also called prepared statements). In Entity Framework Core, LINQ-to-SQL automatically parameterizes queries; when writing raw SQL with context.Database.ExecuteSqlRaw(), use the @parameter placeholders and pass values as separate arguments, never interpolated into the string. Validate and sanitize user input on the server side as a defense-in-depth layer, but parameterization is the primary defense.
What Comes After This Chapter
After mastering the five pillars of application security, you will be equipped to design security controls into new projects from the ground up, audit existing code for vulnerabilities, respond to security incidents, and communicate security requirements to stakeholders and external auditors. Security is an ongoing practice—you will learn to stay current with emerging threats, keep your dependencies patched, and conduct regular security reviews as part of your development workflow.