Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
57 views57 pages

Security Best Practices in Coding

The document outlines security best practices in coding to prevent vulnerabilities such as data leaks and injections by emphasizing safe coding techniques. It highlights the importance of secure coding for protecting user data, avoiding legal issues, and maintaining company reputation, while providing core principles and examples for various programming languages. Additionally, it discusses the OWASP Top 10 security vulnerabilities and offers guidelines for secure coding in Python and Java.

Uploaded by

Ash Ketchum
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
57 views57 pages

Security Best Practices in Coding

The document outlines security best practices in coding to prevent vulnerabilities such as data leaks and injections by emphasizing safe coding techniques. It highlights the importance of secure coding for protecting user data, avoiding legal issues, and maintaining company reputation, while providing core principles and examples for various programming languages. Additionally, it discusses the OWASP Top 10 security vulnerabilities and offers guidelines for secure coding in Python and Java.

Uploaded by

Ash Ketchum
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 57

Security Best Practices in Coding

What Are Security Best Practices in Coding?

Security best practices in coding are techniques used to prevent security


vulnerabilities (like data leaks, injections, or breaches) before they happen — by
writing safe, defensive, and robust code.

Just like unit testing ensures correctness, secure coding ensures safety from hackers
and misuse.

Why Security Matters for Developers

1 small bug in your code can lead to huge damage — like leaking user passwords,
exposing payment info, or allowing full server access.

• Protects users’ data and privacy

• Prevents legal/compliance issues (e.g., GDPR, HIPAA)

• Avoids breaches that ruin company reputation

• Saves time vs fixing after attacks

Core Principles of Secure Coding

Principle Explanation

Never trust user input. Always check and sanitize


Validate Inputs
it.

Escape Outputs Prevent injection attacks by encoding output.

Use Authentication &


Verify who the user is and what they can do.
Authorization Properly

Use hashing (e.g., bcrypt, Argon2). Never store


Store Passwords Securely
plain text passwords.

Encrypt communication between client and


Use HTTPS
server.
Principle Explanation

Handle Errors Safely Don’t expose stack traces or internal info in errors.

Keep Dependencies Updated Old libraries can have known exploits.

Give only the minimum access needed — to users


Least Privilege Principle
and services.

🛠 Examples by Language

Python / FastAPI Example

# Dangerous: vulnerable to SQL Injection

query = f"SELECT * FROM users WHERE email = '{user_email}'"

cursor.execute(query)

# Secure: use parameterized queries

cursor.execute("SELECT * FROM users WHERE email = %s", (user_email,))

Java / Spring Boot Example

// Don't do this

String query = "SELECT * FROM users WHERE id = " + userInput;

// Do this instead

PreparedStatement ps = connection.prepareStatement("SELECT * FROM users WHERE


id = ?");

ps.setInt(1, userId);

Best Practices in Code

• Always validate and sanitize inputs (pydantic in FastAPI helps!)

• Use prepared statements (avoid raw SQL)

• Use HTTPS and environment variables (never hard-code secrets)


• Don’t log sensitive info (passwords, tokens)

• Limit file uploads: size, type, and path

• Set proper HTTP headers (X-Content-Type-Options, Strict-Transport-Security)

Secure Coding Tools

Tool Use

Bandit (Python) Scans for insecure code patterns

SonarQube Finds bugs, vulnerabilities, and code smells

OWASP Dependency-Check Detects vulnerable packages

Black Duck / Snyk Commercial tools to scan for security issues

JWT.io Debugger To validate JSON Web Tokens (JWTs)

Security Mindset for Developers

Think like an attacker, code like a defender.

• Never assume input is safe

• Add security to your definition of done

• Review and test security like any other feature


OWASP Top 10 Security Vulnerabilities (2021 Edition)

Here’s a simplified table with each item, explanation, and example:

# Category Explanation Example

Users can access data or A normal user accessing


1 Broken Access Control
actions they shouldn’t. /admin routes

Weak or missing
Sending passwords over HTTP
2 Cryptographic Failures encryption leads to data
instead of HTTPS
exposure.

Attacker injects code via


3 Injection user inputs (e.g., SQL, ' OR 1=1-- in a login form
NoSQL, LDAP).

Poor security design or No rate-limiting or abuse


4 Insecure Design
missing threat modeling. checks

Security Wrong server, framework, Leaving debug mode on in


5
Misconfiguration or cloud configs. production

Vulnerable & Outdated Using libraries with known Using Log4j with the Log4Shell
6
Components security flaws. exploit

Identification &
Session IDs not rotating after
7 Authentication Weak login mechanisms.
login
Failures

Software & Data Trusting unverified code or Using unsigned third-party


8
Integrity Failures CI/CD artifacts. packages

Security Logging & Missing or weak Breach goes undetected for


9
Monitoring Failures monitoring, alerts, or logs. months

Server-Side Request Server makes unintended Attacker gets server to call


10
Forgery (SSRF) external requests. http://localhost/admin
What Developers Should Do

Vulnerability How to Protect

Injection Use parameterized queries (no string concat in SQL)

Access Control Use role-based permissions (RBAC)

Cryptographic Always use HTTPS, hash passwords (bcrypt), avoid custom


Failures encryption

Security Misconfig Disable debug logs, restrict CORS, review cloud configs

Logging Failures Enable logs, but avoid logging sensitive info (tokens, passwords)

SSRF Whitelist URLs, validate all outbound requests


🛡 OWASP Top 10 – Explained in Easy Language

1. Broken Access Control

What it means: Users can access things they shouldn’t.

Imagine: A student logging in to a school portal can access the teacher’s


dashboard. Oops!

How to fix:

• Always check roles and permissions on the server.

• Never rely on frontend (UI) to hide or disable buttons.

• Use role-based access control (RBAC).

# FastAPI example

@app.get("/admin")

def admin_data(current_user: User = Depends(get_user)):

if not current_user.is_admin:

raise HTTPException(status_code=403)

2. Cryptographic Failures

(Previously called: Sensitive Data Exposure)

What it means: Not protecting data in transit or at rest (bad encryption or none at
all).

Imagine: Sending a credit card number over HTTP – anyone can steal it!

How to fix:

• Always use HTTPS

• Hash passwords (bcrypt, argon2)

• Don’t log sensitive data

• Use proper SSL/TLS certificates


# Python: storing passwords securely

import bcrypt

hashed = bcrypt.hashpw(b"password123", bcrypt.gensalt())

3. Injection (SQL, NoSQL, etc.)

What it means: Attackers put malicious code into inputs, which gets executed by
the server.

Imagine: A login form where the user enters: ' OR 1=1 --, and it logs them in without
a password.

How to fix:

• Never build SQL with string concatenation

• Use parameterized queries

# Python (safe query)

cursor.execute("SELECT * FROM users WHERE email = %s", (user_email,))

4. Insecure Design

What it means: Your app design is flawed — even before coding.

🏗 Imagine: You built a house with no locks on the doors.

How to fix:

• Design for security: add rate-limiting, logging, verification steps

• Do threat modeling

• Add security into sprint planning and system design

5. Security Misconfiguration

What it means: Your server or app has the wrong settings.

Example:

• Default passwords still enabled

• CORS open to all (*)


• Dev/debug mode enabled in production

How to fix:

• Turn off debug mode in prod

• Review cloud security rules

• Use tools like Docker Bench, AWS Trusted Advisor

6. Vulnerable and Outdated Components

What it means: You use old libraries or dependencies with known security issues.

Imagine: You still use a version of Log4j that hackers already know how to break.

How to fix:

• Keep dependencies updated

• Use tools like pip-audit, OWASP Dependency-Check, Snyk

# Check Python package vulnerabilities

pip install pip-audit

pip-audit

7. Identification & Authentication Failures

What it means: Authentication (login) is broken or weak.

Example:

• Users can reuse old session tokens

• No account lockout after failed login attempts

How to fix:

• Use multi-factor authentication (MFA)

• Rotate session tokens after login

• Use libraries like FastAPI Users or Spring Security


8. Software & Data Integrity Failures

What it means: You’re trusting things that might have been tampered with.

Example:

• Using plugins from unknown sources

• Auto-deploying from GitHub without verification

How to fix:

• Use signed packages (PyPI and Maven support this)

• Validate file hashes

• Don’t blindly run scripts from the internet

9. Security Logging & Monitoring Failures

What it means: You’re blind to attacks — no logs, alerts, or tracking.

Imagine: An attacker is inside your system, but you have no logs, so you can’t tell.

How to fix:

• Log important actions (logins, errors, failed logins)

• Use a central logging system (like ELK, CloudWatch, Splunk)

• Set up alerts for suspicious behavior

10. Server-Side Request Forgery (SSRF)

What it means: An attacker tricks your server into making requests to internal or
sensitive services.

Example: Your API lets users enter a URL to fetch. They give http://localhost/admin,
and your server calls it!

How to fix:

• Validate URLs before making any requests

• Block internal IP ranges (127.0.0.1, 169.254.x.x, etc.)

• Use firewalls and access controls


Summary Table

OWASP # Risk Fix Strategy

1 Broken Access Control Enforce strict backend checks

2 Cryptographic Failures Use HTTPS, hash passwords

3 Injection Parameterized queries

4 Insecure Design Think security in design phase

5 Misconfiguration Review server & app settings

6 Outdated Components Keep libraries up-to-date

7 Auth Failures Secure login, sessions

8 Integrity Failures Use signed packages, verify

9 Logging Failures Log & monitor key actions

10 SSRF Block server-side fetch abuse


Secure Coding Guidelines for Python (FastAPI)

1. Input Validation & Sanitization

Why? To protect against injection attacks and malformed input.

Do:

• Use Pydantic models for type validation.

• Use regex or enums to restrict accepted values.

• Strip unwanted fields using extra=forbid.

from pydantic import BaseModel, Field, EmailStr

class UserCreate(BaseModel):

name: str = Field(..., max_length=50)

email: EmailStr

age: int = Field(..., ge=18, le=100)

class Config:

extra = "forbid" # Disallow unexpected fields

2. Authentication & Authorization

Why? Prevent unauthorized access to resources.

Do:

• Use OAuth2, JWT tokens, or fastapi-users.

• Protect sensitive routes with Depends(get_current_user).

• Check roles and permissions inside route handlers.


from fastapi import Depends, HTTPException

from .dependencies import get_current_user

@app.get("/admin/dashboard")

def read_admin_dashboard(current_user: User = Depends(get_current_user)):

if not current_user.is_admin:

raise HTTPException(status_code=403, detail="Not authorized")

3. Secure Password Handling

Why? Passwords must never be stored in plaintext.

Do:

• Use bcrypt or passlib for hashing passwords.

• Never log or return passwords in any response.

from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def hash_password(password: str):

return pwd_context.hash(password)

def verify_password(plain, hashed):

return pwd_context.verify(plain, hashed)

4. Dependency Management

Why? Vulnerable libraries can compromise your app.

Do:

• Pin dependency versions (requirements.txt)

• Run security audits:


pip install pip-audit

pip-audit

• Avoid unknown or unofficial packages.

5. Use HTTPS in Production

Why? HTTP exposes passwords, tokens, and data.

Do:

• Use HTTPS (via reverse proxy like NGINX).

• Enforce HTTPS-only cookies (Secure=True).

6. Avoid Leaking Sensitive Info

Do:

• Don’t print or log secrets, passwords, tokens.

• Use .env files and environment variables.

# .env

DATABASE_URL=postgresql://user:pass@localhost/db

from dotenv import load_dotenv

import os

load_dotenv()

db_url = os.getenv("DATABASE_URL")

7. Prevent Path Traversal and File Upload Abuse

Do:

• Validate file extensions and names.

• Sanitize filenames using secure_filename.


from werkzeug.utils import secure_filename

filename = secure_filename(uploaded_file.filename)

8. CSRF & CORS Protections

Do:

• Use CORSMiddleware to allow only trusted origins.

• Protect against CSRF if you use session-based auth.

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(

CORSMiddleware,

allow_origins=["https://yourfrontend.com"],

allow_credentials=True,

allow_methods=["GET", "POST"],

allow_headers=["*"],

9. Set Secure HTTP Headers

Use a reverse proxy (like NGINX) or middleware like Starlette’s


HTTPSRedirectMiddleware and security headers middleware.

from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware

from starlette.middleware.trustedhost import TrustedHostMiddleware

app.add_middleware(HTTPSRedirectMiddleware)

app.add_middleware(TrustedHostMiddleware, allowed_hosts=["yourdomain.com"])
10. Logging and Monitoring

Why? Detect and respond to breaches or suspicious activity.

Do:

• Log logins, password changes, failed logins, admin actions.

• Use structured logging (loguru, structlog).

• Avoid logging sensitive data like tokens or PII.

11. Common Things to Avoid

Bad Practice Better Practice

Storing plain passwords Hash with bcrypt or argon2

Using eval() or exec() Avoid entirely

Accepting any user input as-is Use Pydantic + regex + enums

Trusting frontend auth Always recheck user permissions on backend

Hardcoding secrets in code Use environment variables + .env files

Exposing stack traces in prod Catch exceptions, return generic error messages

Summary Checklist for FastAPI Security

Area Best Practice

Input Validation Use Pydantic, regex, enums

JWT/OAuth2, password
Authentication
hashing

Authorization Backend role checks, RBAC

Secrets Use .env, don’t log secrets

Dependencies Run pip-audit, pin versions

Sanitize filenames, restrict


File Uploads
types
Area Best Practice

CORS Allow only trusted origins

Log safely, use structured


Logging
loggers

Set strict headers, use HTTPS


HTTP Headers
in prod
Secure Coding Guidelines for Java (Spring Boot)

1. Input Validation & Sanitization

Why? Prevent malicious input (e.g., SQL Injection, XSS).

Do:

• Use Bean Validation (javax.validation.constraints)

• Sanitize input strings using libraries like ESAPI if needed

public class UserDTO {

@NotNull

@Size(max = 50)

private String name;

@Email

private String email;

@Min(18)

@Max(100)

private int age;

And apply it:

@PostMapping("/register")

public ResponseEntity<?> registerUser(@Valid @RequestBody UserDTO user) {

// Safe handling

}
2. Authentication & Authorization

Why? To restrict access to sensitive resources.

Do:

• Use Spring Security

• Secure endpoints with roles and permissions

• Enable JWT or OAuth2 for stateless APIs

@PreAuthorize("hasRole('ADMIN')")

@GetMapping("/admin/dashboard")

public String adminDashboard() {

return "Welcome Admin!";

Use @EnableGlobalMethodSecurity(prePostEnabled = true) to activate.

3. Secure Password Storage

Why? Storing raw passwords is a critical risk.

Do:

• Use BCryptPasswordEncoder for hashing

• Never log or send passwords in responses

@Bean

public PasswordEncoder passwordEncoder() {

return new BCryptPasswordEncoder();

4. Dependency Management

Why? Vulnerabilities often come from third-party libraries.

Do:

• Use dependency-check plugin (OWASP)


• Regularly check dependencies with:

mvn dependency-check:check

• Use only trusted libraries.

5. Prevent SQL Injection

Do:

• Use Spring Data JPA or Hibernate (prepared statements)

• Never concatenate user input into SQL

@Query("SELECT u FROM User u WHERE u.email = :email")

User findByEmail(@Param("email") String email);

6. Cross-Site Scripting (XSS) Prevention

Do:

• Escape outputs in HTML using frameworks like Thymeleaf

• Sanitize input on both frontend and backend

Thymeleaf escapes HTML by default:

<p th:text="${user.name}"></p>

7. Cross-Site Request Forgery (CSRF)

Do:

• CSRF is enabled by default in Spring Security

• For stateless APIs (JWT), you can disable CSRF:

http.csrf().disable();

8. Use HTTPS in Production

Do:

• Always serve your app over HTTPS


• Set secure cookies:

server.servlet.session.cookie.secure=true

9. Avoid Exposing Sensitive Information

Do:

• Never return stack traces in production

• Customize exception handlers using @ControllerAdvice

@ControllerAdvice

public class GlobalExceptionHandler {

@ExceptionHandler(Exception.class)

public ResponseEntity<?> handleException(Exception ex) {

return ResponseEntity.status(500).body("Something went wrong");

10. Security Headers

Set common headers using Spring Security config:

http

.headers()

.contentSecurityPolicy("script-src 'self'")

.xssProtection()

.frameOptions().deny();

11. Avoid Hardcoding Secrets

Do:

• Store secrets in environment variables or .properties files.

• Use tools like Spring Cloud Vault or AWS Secrets Manager.


# application.properties

db.password=${DB_PASSWORD}

Summary Table: Secure Spring Boot Practices

Area Best Practice

Input Validation Use @Valid, @NotNull, @Size, etc.

Authentication Use Spring Security, JWT, OAuth2

Passwords Store hashed using BCrypt

SQL Injection Use JPQL / prepared queries

XSS Escape output in views (Thymeleaf)

CSRF Enabled by default (disable for stateless JWT)

HTTPS Enforce HTTPS, Secure cookies

Exception Leaks Use @ControllerAdvice, avoid stack traces

Dependency Safety Run OWASP dependency-check

Secrets Handling Use environment variables, not hardcoding

Tools to Integrate

Tool Purpose

OWASP Zap Penetration testing

SonarQube Static analysis, vulnerability scan

Spring Security Core security framework

Maven plugin – OWASP Dependency vulnerability check

Snyk Real-time vuln scan for dependencies


✅ Input Validation & Data Sanitization in FastAPI (In
Depth)

Why It Matters

Input validation and sanitization protect your application from:

• Invalid or malicious input (e.g., SQL Injection, XSS, security attacks)

• Crashes due to wrong data types

• Unexpected behavior from missing or bad input

Key Concepts

Concept Purpose

Validation Ensures data is correct and expected

Sanitization Cleans/removes unwanted characters

Schema (Pydantic) Defines data types and rules

FastAPI Uses Pydantic for Input Validation

Pydantic models power FastAPI's request parsing. You define what data is expected,
and FastAPI automatically:

• Parses JSON

• Validates types and constraints

• Returns 422 Unprocessable Entity if input is invalid


Example 1: Basic Input Validation with Pydantic

from fastapi import FastAPI

from pydantic import BaseModel, Field, EmailStr

app = FastAPI()

class User(BaseModel):

name: str = Field(..., max_length=50)

email: EmailStr

age: int = Field(..., ge=18, le=100)

@app.post("/register")

def register_user(user: User):

return {"message": f"Welcome {user.name}"}

What’s Validated?

• name: required, string, max 50 chars

• email: must be a valid email

• age: must be 18 to 100


Example 2: Custom Validation with Pydantic

from pydantic import validator

class User(BaseModel):

username: str

password: str

@validator("password")

def strong_password(cls, v):

if len(v) < 8:

raise ValueError("Password must be at least 8 characters")

return v

Input Sanitization

Validation checks correctness, sanitization removes or escapes bad input.

While Pydantic does not auto-sanitize (like removing HTML tags), you can manually
sanitize:

Example 3: Manual Input Sanitization

import re

def sanitize_text(text: str) -> str:

# Remove HTML tags

return re.sub(r'<.*?>', '', text)

@app.post("/submit-comment")

def submit(comment: str):

clean = sanitize_text(comment)
return {"sanitized": clean}

Security-Focused Validation & Sanitization Tips

Attack Type Prevention Strategy

SQL Injection Use ORMs like SQLAlchemy (avoid raw SQL with user input)

XSS Sanitize strings before rendering in frontend (e.g., remove <script>)

Path Traversal Use Path() from FastAPI to validate paths, avoid file injections

Invalid Input Use Pydantic for schema-level validation

Optional: Use Third-Party Libraries for Sanitization

• bleach – for HTML/XSS sanitization

• python-slugify – for clean URLs

Example with bleach:

import bleach

@app.post("/safe-message")

def safe_msg(msg: str):

safe = bleach.clean(msg)

return {"safe": safe}

Best Practices Checklist

Define input schemas with Pydantic


Use Field() for type constraints
Validate data length, formats, enums
Sanitize user-generated strings before storing or displaying
Never trust query parameters or JSON bodies as-is
Log validation failures (in production logs, not to users)
Return helpful but safe error messages (no stack traces)
Test Invalid Input

Test your API by sending:

"name": "Hacker<script>alert(1)</script>",

"email": "bademail.com",

"age": -5

FastAPI will reject it with detailed error messages!


Input validation and data sanitization in Spring Boot
Why Input Validation and Sanitization Matter

In Spring Boot applications, user input is typically accepted via:

• @RequestBody (JSON from frontend)

• @RequestParam (query params)

• @PathVariable (URL path parts)

• HTML Forms (for web apps)

You must never trust user input. Attackers often inject invalid or malicious data (e.g.,
SQL, script tags, long inputs).

Core Concepts

Concept What it Does

Validation Checks input format, value range, etc.

Sanitization Cleans or escapes unwanted characters

Spring Boot Tools for Input Validation

Tool Purpose

Built-in annotations like @NotNull,


javax.validation (Jakarta Bean Validation)
@Email, etc.

Used to trigger validation on request


@Valid / @Validated
body or params

BindingResult or
Used to handle validation errors
MethodArgumentNotValidException

Write your own rules beyond built-in


Custom Validators
ones
Step-by-Step: Input Validation with Example

1. Maven Dependencies (if using Spring Boot < 3)

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-validation</artifactId>

</dependency>

2. DTO with Validation Annotations

import jakarta.validation.constraints.*;

public class UserDTO {

@NotBlank(message = "Name is required")

@Size(max = 50)

private String name;

@Email(message = "Invalid email")

private String email;

@Min(18)

@Max(100)

private int age;

// Getters and setters

}
3. Controller Using @Valid

import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;

@RestController

@RequestMapping("/users")

public class UserController {

@PostMapping("/register")

public String register(@RequestBody @Valid UserDTO user) {

return "User registered: " + user.getName();

4. Error Handling (Optional)

Create a @ControllerAdvice to return custom validation error responses:

@RestControllerAdvice

public class ValidationExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)

public ResponseEntity<?>
handleValidationErrors(MethodArgumentNotValidException ex) {

Map<String, String> errors = new HashMap<>();

ex.getBindingResult().getFieldErrors()

.forEach(err -> errors.put(err.getField(), err.getDefaultMessage()));

return ResponseEntity.badRequest().body(errors);

}
Input Sanitization in Spring Boot

Spring doesn't auto-sanitize inputs like stripping HTML — you must manually sanitize
fields that may hold text input from users.

Common Techniques

1. Escape HTML Using Apache Commons Text

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-text</artifactId>

</dependency>

import org.apache.commons.text.StringEscapeUtils;

public String sanitize(String input) {

return StringEscapeUtils.escapeHtml4(input); // Remove <script> etc.

2. Prevent SQL Injection

Use JPA or Spring Data Repositories


Avoid building raw SQL strings from user input

Best Practices Table

Input Type Validation Approach Sanitization Needed?

JSON body @Valid, DTO classes Yes (for text input)

Query params @RequestParam + validation annotations Optional

Path variables Use @PathVariable + enum/type checks Optional

Form data Use Spring Forms with HTML escaping Yes


What to Avoid

Mistake Why it's Dangerous

Trusting raw request values Opens door for XSS, injection

Not validating enums/IDs Attackers can tamper inputs

Echoing user input in HTML directly XSS vulnerability

Bonus: Custom Validation Example

@Constraint(validatedBy = NoSpecialCharsValidator.class)

@Target({ ElementType.FIELD })

@Retention(RetentionPolicy.RUNTIME)

public @interface NoSpecialChars {

String message() default "Special characters not allowed";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

public class NoSpecialCharsValidator implements


ConstraintValidator<NoSpecialChars, String> {

public boolean isValid(String value, ConstraintValidatorContext context) {

return value != null && value.matches("^[a-zA-Z0-9 ]*$");

Use it like:

@NoSpecialChars

private String username;


Summary Checklist

• Use @Valid in controllers

• Use DTO classes with @NotBlank, @Size, @Email, etc.

• Manually sanitize input that could be rendered (e.g., names, comments)

• Avoid raw SQL — use ORM (Hibernate/JPA)

• Escape or sanitize text fields before storage/display

• Always handle invalid input with safe error responses


Authentication and authorization best practices

Authentication vs Authorization

Term Meaning

Authentication Verifies who the user is (e.g., login with token, OAuth, etc.)

Authorization Verifies what the authenticated user is allowed to do (e.g., roles)

Common Authentication Methods in FastAPI

Method Description Use When...

Username/password in header Rarely used, mostly for internal


Basic Auth
(insecure) APIs

OAuth2 / JWT Token-based authentication Most secure and scalable

API Key Simple token passed via header/query For machine-to-machine APIs

Session
For browser-based login systems If building full-stack web apps
Cookies

Authentication with OAuth2 + JWT (Recommended)

FastAPI provides first-class support for OAuth2 with JWT (JSON Web Tokens).

1. Install Required Libraries

pip install fastapi[all] python-jose[cryptography] passlib[bcrypt]

2. Create Token Utilities

# auth_utils.py

from jose import JWTError, jwt

from datetime import datetime, timedelta

SECRET_KEY = "your_secret"
ALGORITHM = "HS256"

ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_access_token(data: dict, expires_delta: timedelta = None):

to_encode = data.copy()

expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))

to_encode.update({"exp": expire})

return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

3. Set Up Dependency to Verify Token

from fastapi import Depends, HTTPException, status

from fastapi.security import OAuth2PasswordBearer

from jose import JWTError, jwt

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

def get_current_user(token: str = Depends(oauth2_scheme)):

try:

payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])

username = payload.get("sub")

if username is None:

raise HTTPException(status_code=401, detail="Invalid credentials")

return {"username": username}

except JWTError:

raise HTTPException(status_code=401, detail="Invalid token")


4. Protect Routes

@app.get("/users/me")

def read_users_me(current_user: dict = Depends(get_current_user)):

return current_user

Authorization with Roles/Scopes

Example: Require Admin Role

def get_current_admin(current_user=Depends(get_current_user)):

if current_user["username"] != "admin":

raise HTTPException(status_code=403, detail="Not enough permissions")

return current_user

Use it in a route:

@app.get("/admin")

def admin_dashboard(current_user=Depends(get_current_admin)):

return {"msg": "Welcome Admin"}

🛡 Best Practices for Authentication & Authorization in FastAPI

1. Always use HTTPS in production

• Never transmit tokens or passwords over plain HTTP.

• Use https:// and secure cookies if needed.

2. Use JWT tokens securely

• Set expiration (exp) claim

• Use secure secret keys (SECRET_KEY)

• Rotate keys periodically


3. Store hashed passwords

Use passlib to hash passwords (e.g., bcrypt):

from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def hash_password(password):

return pwd_context.hash(password)

def verify_password(plain, hashed):

return pwd_context.verify(plain, hashed)

4. Implement Role-Based Access Control (RBAC)

Store roles in your user model and check roles before actions.

Example:

if current_user["role"] != "admin":

raise HTTPException(status_code=403)

5. Prevent JWT replay attacks

• Set short expiration (15–30 minutes)

• Store token identifiers in DB if needed

• Use refresh tokens for longer sessions

6. Log security-related events

• Login attempts

• Token refresh

• Unauthorized access attempts


7. Use OAuth2 for third-party login (optional)

Use fastapi-login, authlib, or python-social-auth to integrate Google/GitHub login.

Secure Cookie-based Sessions (Alternative to JWT)

Use if you're building full-stack apps with FastAPI + Jinja.

• Use response.set_cookie() with HttpOnly, Secure, SameSite flags.

• Avoid storing sensitive data directly in cookies.

Libraries & Tools to Explore

• python-jose – JWT encoding/decoding

• passlib – Secure password hashing

• fastapi-users – Full user auth system

• authlib – For advanced OAuth2/OpenID support

Summary

Checklist Status

Use JWT + OAuth2 securely

Protect sensitive routes with roles

Hash passwords with bcrypt

Implement token expiration

Avoid exposing sensitive info

Log auth events and errors


Authentication and authorization best practices in Spring Boot

What’s the Difference?

Term Description

Authentication Verifies who you are (e.g., via login credentials)

Authorization Verifies what you are allowed to do (e.g., roles, scopes)

Common Authentication Methods in Spring Boot

Method Use Case

Basic Auth Simple login for internal tools or testing

Form-based login Web applications with UI

JWT (Stateless) Modern REST APIs

OAuth2 Third-party login via Google/GitHub/etc.

Session-based Traditional web apps

Spring Security Basics

Maven Dependency (Spring Boot Starter)

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-security</artifactId>

</dependency>

Basic Flow with JWT

1. User sends login credentials to /login

2. Spring authenticates and returns a JWT

3. User includes JWT in Authorization: Bearer <token> header in future requests


4. Spring validates token, extracts identity & roles

Best Practices: Authentication in Spring Boot

1. Use BCrypt for Password Hashing

Hash and store passwords safely.

@Bean

public PasswordEncoder passwordEncoder() {

return new BCryptPasswordEncoder();

Use passwordEncoder.encode(plainPassword) to hash passwords.

2. JWT Token Generation & Validation

• Use libraries like jjwt or auth0/java-jwt

• Add expiration to tokens

• Never store sensitive info in JWT payload

Sample filter:

// Custom filter to validate JWT

public class JwtRequestFilter extends OncePerRequestFilter {

// Extract token and validate

3. Secure APIs with Role-based Access

@Override

protected void configure(HttpSecurity http) throws Exception {

http

.authorizeRequests()

.antMatchers("/admin/**").hasRole("ADMIN")

.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()

.and()

.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

4. Protect Sensitive Endpoints

Use annotations:

@PreAuthorize("hasRole('ADMIN')")

@GetMapping("/admin/data")

public ResponseEntity<?> adminOnly() { ... }

Enable via:

@EnableGlobalMethodSecurity(prePostEnabled = true)

5. Don’t Hardcode Secrets

Use application.yml or Spring Config Server for secrets.

jwt:

secret: ${JWT_SECRET}

6. Enable HTTPS in Production

• Never allow credentials or tokens over plain HTTP.

• Use reverse proxy (e.g., Nginx) to enforce SSL.

Best Practices: Authorization in Spring Boot

Principle Best Practice Example

Least privilege Give minimum necessary roles to users

Role hierarchy Define structured access: ADMIN > MANAGER > USER

Centralized role check Avoid hardcoding if (user.role == ...) all over


Principle Best Practice Example

Use annotations @PreAuthorize, @Secured, etc.

Session vs JWT

Feature Session-Based JWT-Based (Stateless)

Storage Server memory Client-side

Scalability Limited (server-bound) Highly scalable

Recommended Full web apps REST APIs, microservices

🛡 Tips for Secure Spring Boot Apps

1. Set security headers

http

.headers()

.xssProtection()

.and()

.contentSecurityPolicy("script-src 'self'");

2. Limit login attempts


Prevent brute-force attacks.

3. Enable CSRF only for web apps


Disable for APIs:

http.csrf().disable();

4. Use HTTPS everywhere

5. Log security events


Log authentication, errors, and denied access for auditing.
Recommended Libraries/Tools

Tool Purpose

Spring Security AuthN + AuthZ framework

jjwt JWT creation/validation

OAuth2 client Google, GitHub login integration

BCrypt Secure password hashing

Summary Checklist

Practice Done?

Use Spring Security

Hash passwords with BCrypt

Secure API routes with roles

Use JWT for stateless auth (REST)

Never hardcode credentials

Enable HTTPS in production

Log security events


Security Code Review Checklist

1. Authentication

• Are strong password policies enforced?

• Are passwords hashed using a strong algorithm (e.g., BCrypt, Argon2)?

• Is multi-factor authentication (MFA) supported for sensitive areas?

• Is the authentication mechanism stateless (JWT) or session-based, and is it


appropriate for the use case?

• Is the login endpoint protected against brute-force attacks (e.g., rate limiting)?

2. Authorization

• Are users authorized based on roles/permissions?

• Is access control enforced at both API layer and business logic layer?

• Are endpoints annotated with role restrictions (@PreAuthorize,


Depends(get_current_user) in FastAPI)?

• Are sensitive actions (like user deletion) double-checked for correct roles?

3. Input Validation & Output Encoding

• Is all user input validated on both client and server side?

• Are data types, formats, and lengths strictly checked (e.g., using Pydantic in
FastAPI or Bean Validation in Java)?

• Is untrusted input never inserted directly into HTML, SQL, or command lines?

• Are HTML/JS outputs properly escaped to avoid XSS?

4. Data Protection

• Is HTTPS enforced on all environments (not just production)?

• Are sensitive data fields encrypted at rest (e.g., credit cards)?

• Is JWT signed using a secure algorithm (e.g., RS256, HS256) and properly
validated?
• Are secrets, tokens, and keys stored in secure configs or environment variables?

5. Error Handling & Logging

• Are detailed error messages hidden from users (e.g., no stack traces)?

• Are security events logged (logins, failed attempts, permission denials)?

• Are logs scrubbed to avoid storing sensitive data (e.g., passwords, tokens)?

• Are logs rotated and access-controlled?

6. Dependency and Package Security

• Are you using a vulnerability scanner (e.g., Dependabot, Snyk, OWASP


Dependency-Check)?

• Are dependencies locked using version pinning (requirements.txt, pom.xml)?

• Are unused libraries or services removed?

• Are third-party libraries vetted and well-maintained?

7. Session Management

• Are sessions invalidated on logout?

• Is there an expiration mechanism for JWT or sessions?

• Is session ID stored securely (e.g., HttpOnly, Secure cookies)?

• Is session fixation prevented (regenerate session IDs after login)?

8. Secure Configuration

• Is debug mode disabled in production (DEBUG = False,


spring.profiles.active=prod)?

• Are security headers used? (CSP, X-Frame-Options, etc.)

• Are CORS policies properly configured (avoid '*' in production)?

• Are sensitive files (.env, settings.py, application.properties) excluded from


version control?
9. File Uploads

• Are file types validated on upload?

• Are uploaded files stored outside the web root or scanned for malware?

• Are filename/path sanitization and size limits applied?

10. API Security

• Is rate limiting enabled for public endpoints?

• Are APIs protected using tokens (JWT, API Keys, OAuth2)?

• Are GraphQL/REST endpoints checked for excessive data exposure?

• Are OPTIONS/TRACE methods disabled unless required?

11. Code-Specific Checks

• Are SQL queries parameterized? (to avoid SQL Injection)

• Are command line executions sanitized? (subprocess, Runtime.getRuntime)

• Are temporary files and user data cleaned up securely?

• Are background jobs (cron, async tasks) validated and authenticated?

Optional: Security Review Tags for PRs

Include tags or comments like:

#SECURITY-INPUT-VALIDATION

#SECURITY-AUTH

#SECURITY-FILE-UPLOAD

To help security engineers during PR reviews.

Recommended Tools

Tool Purpose

SonarQube Code quality + security detection


Tool Purpose

Bandit (Python) Static analysis for security in Python

OWASP ZAP Dynamic app security testing

Snyk Dependency scanning

Dependabot GitHub-based auto-patching


Code encryption and obfuscation

Code Encryption vs Obfuscation

Feature Encryption Obfuscation

Transforms code into ciphertext Transforms code into difficult-to-


What it is
using encryption algorithms understand versions

To protect code/data at rest or in To prevent easy reverse engineering


Purpose
transit or understanding of the source

Mostly for storing/deploying code Mostly for client-side apps or


When used
or secrets securely distributed binaries

Who The system or application itself No decryption — runs as-is, but is


decrypts it (during runtime or build) hard to understand

Encrypting Python .pyc files; Renaming variables to a, b, c;


Examples
encrypting config files making control flow unreadable

1. Why Use These Techniques?

• Prevent IP theft (especially in frontend or distributed apps)

• Make reverse engineering harder (useful in Java/.NET which are easy to


decompile)

• Hide business logic or license checks

• Protect API keys or credentials (though this should be avoided—best stored


securely)

2. Obfuscation in Practice

Java Obfuscation

Java bytecode is easy to reverse engineer with tools like JD-GUI, so Java apps often use:

Tools:

• ProGuard: Popular tool for Android & Java apps.

• DexGuard: Commercial alternative for Android.


• yGuard, Zelix KlassMaster

What it does:

• Renames classes/methods/variables (UserManager → a)

• Strips out debug symbols and unused code

• Encrypts string literals

• Flattens control flow

Example:

Before:

public class UserService {

public boolean isUserLoggedIn(String username) { ... }

After ProGuard:

public class a {

public boolean a(String a) { ... }

Python Obfuscation

Python is interpreted and open, making it easy to inspect source. You can obfuscate it
using:

Tools:

• Pyarmor

• Nuitka (compiles to C)

• Cython (convert to C extensions)

• pyminifier

These tools:

• Encrypt .py files

• Convert Python code to bytecode or C code

• Obfuscate function and variable names


3. Code Encryption Techniques

Use Cases:

• Encrypting Python .pyc files before deployment

• Storing encrypted config files or secrets

• Java class files encrypted and loaded at runtime

Tools:

• PyArmor: Encrypts .py files and adds a bootloader to decrypt at runtime

• Jasypt (Java): Encrypts sensitive configs

• AES/RSA based loaders: Custom loaders that decrypt encrypted modules on-
the-fly

4. What NOT to Do

• Don’t hide secrets in obfuscated code — they can still be extracted

• Don’t rely solely on obfuscation for security

• Don’t skip proper authorization and validation thinking obfuscation is


enough

Obfuscation is security through obscurity — it should complement, not replace,


security best practices.

5. Best Practices

Goal Best Practice

Prevent
Use obfuscation tools on your Java/.NET builds
decompilation

Secure Python code Use PyArmor, Cython, or freeze to executable with PyInstaller

Encrypt with AES/GPG and use vault tools (e.g., HashiCorp


Secure config/secrets
Vault)

CI/CD protection Run obfuscation/encryption as part of your build pipeline


Great! Let’s do a hands-on exercise where you:

• Identify security vulnerabilities in sample Python (FastAPI) and Java (Spring


Boot) code

• Understand why each issue is dangerous

• Learn how to fix them with secure coding best practices

Hands-On: FastAPI (Python)

Insecure Sample Code

# app.py

from fastapi import FastAPI, Request

import sqlite3

app = FastAPI()

@app.get("/users")

def get_user(name: str):

conn = sqlite3.connect("users.db")

cursor = conn.cursor()

# SQL Injection risk!

cursor.execute(f"SELECT * FROM users WHERE name = '{name}'")

user = cursor.fetchone()

return {"user": user}

Issues:

1. SQL Injection – direct string interpolation in SQL query.

2. No input validation – name is unchecked.

3. No error handling/logging – if DB fails, it crashes.

4. Connection not closed properly – resource leak.


Fixed Secure Version

from fastapi import FastAPI, Query, HTTPException

import sqlite3

app = FastAPI()

@app.get("/users")

def get_user(name: str = Query(..., min_length=1, max_length=50)):

try:

conn = sqlite3.connect("users.db")

cursor = conn.cursor()

# Use parameterized queries

cursor.execute("SELECT * FROM users WHERE name = ?", (name,))

user = cursor.fetchone()

conn.close()

if not user:

raise HTTPException(status_code=404, detail="User not found")

return {"user": user}

except Exception as e:

raise HTTPException(status_code=500, detail="Internal Server Error")

Fixes Applied:

• Parameterized SQL query → prevents SQL injection

• Input validation with Query()

• Exception handling with proper HTTP status

• Closing DB connection
Hands-On: Java (Spring Boot)

Insecure Sample Code

@RestController

public class LoginController {

@PostMapping("/login")

public String login(@RequestParam String username, @RequestParam String


password) {

// Storing plain text password in logs

System.out.println("Login attempt: " + username + " / " + password);

if(username.equals("admin") && password.equals("admin123")) {

return "Welcome!";

} else {

return "Invalid login";

Issues:

1. Logging passwords – major credential leakage risk.

2. Hardcoded credentials – should never be in code.

3. No input validation

4. No authentication mechanism (JWT, session, etc.)


Fixed Secure Version

@RestController

public class LoginController {

@Autowired

private AuthenticationManager authManager;

@PostMapping("/login")

public ResponseEntity<?> login(@RequestBody AuthRequest request) {

try {

UsernamePasswordAuthenticationToken token =

new UsernamePasswordAuthenticationToken(request.getUsername(),
request.getPassword());

Authentication auth = authManager.authenticate(token);

// Generate JWT token here (mocked)

String jwt = JwtUtil.generateToken(request.getUsername());

return ResponseEntity.ok(new AuthResponse(jwt));

} catch (AuthenticationException e) {

return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid
credentials");

// AuthRequest.java
public class AuthRequest {

private String username;

private String password;

// getters/setters

Fixes Applied:

• No sensitive data in logs

• Authentication done using Spring Security

• No hardcoded secrets

• Secure, extendable architecture using JWT or OAuth


Great! Let’s walk through one more FastAPI security hands-on example — this time
focusing on:

• Missing authentication

• Sensitive data exposure

• Lack of rate limiting / protection against brute-force

Insecure FastAPI Code: Login Endpoint

from fastapi import FastAPI, Form

app = FastAPI()

@app.post("/login")

def login(username: str = Form(...), password: str = Form(...)):

# NEVER log credentials!

print(f"Login attempt - username: {username}, password: {password}")

# Hardcoded login logic

if username == "admin" and password == "secret123":

return {"message": "Login successful"}

return {"message": "Invalid credentials"}

Security Problems

Problem Why it’s dangerous

No Authentication Anyone can call this endpoint freely

Logging credentials Exposes sensitive user data in logs

Hardcoded secrets Easily leaked or reused


Problem Why it’s dangerous

No rate limiting Vulnerable to brute-force attacks

No hashing of passwords Passwords compared in plain text

Secure & Improved Version

Here’s a more realistic and secure login flow:

from fastapi import FastAPI, Form, HTTPException, Depends

from passlib.context import CryptContext

from pydantic import BaseModel

from fastapi.security import OAuth2PasswordRequestForm

app = FastAPI()

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# Mock user "database"

users_db = {

"admin": {

"username": "admin",

"hashed_password": pwd_context.hash("secret123")

# Dependency

def authenticate_user(username: str, password: str):

user = users_db.get(username)

if not user:

return False
if not pwd_context.verify(password, user["hashed_password"]):

return False

return user

@app.post("/login")

def login(form_data: OAuth2PasswordRequestForm = Depends()):

user = authenticate_user(form_data.username, form_data.password)

if not user:

raise HTTPException(status_code=401, detail="Invalid username or password")

return {"message": "Login successful", "user": user["username"]}

What Did We Fix?

Fix Explanation

Password hashing Passwords are stored & compared securely

No logging sensitive data No print() of credentials

OAuth2PasswordRequestForm Standard format for login

Proper error handling Uses HTTPException with 401

Authentication logic separated Clean, reusable function

You might also like