Securing Modern Web Applications: Complete Guide to TLS 1.3 and AES-256 Implementation in React/.NET Core/PostgreSQL Stack

PP

Ponvannan P

Jun 25, 2025 12 Minutes Read

Securing Modern Web Applications: Complete Guide to TLS 1.3 and AES-256 Implementation in React/.NET Core/PostgreSQL Stack Cover

Introduction

In 2025, data breaches cost organizations an average of $4.88 million per incident, with 83% of breaches involving web applications. As cybersecurity threats evolve, implementing robust encryption standards like TLS 1.3 and AES-256 has become non-negotiable for modern web applications.

This comprehensive guide walks you through implementing enterprise-grade security across a complete technology stack: React frontend, .NET Core microservices, and PostgreSQL database. You'll learn not just the "what" but the "how" with production-ready code examples.

What You'll Learn

  • How to configure TLS 1.3 for maximum security and performance

  • Implementing AES-256 encryption across your entire application stack

  • Best practices for key management and secure communication

  • Real-world code examples and configuration templates

  • Performance optimization techniques for encrypted applications


Understanding Modern Encryption Standards

TLS 1.3: The Security Revolution

TLS 1.3, ratified in 2018, represents the most significant upgrade to transport layer security in over a decade. Here's why it matters:

Key Improvements:

  • Reduced Handshake Latency: 1-RTT (Round Trip Time) vs 2-RTT in TLS 1.2

  • Perfect Forward Secrecy: Always enabled, not optional

  • Simplified Cipher Suites: Removed weak and deprecated algorithms

  • Enhanced Privacy: Encrypted handshake messages

Performance Benefits:

TLS 1.2 Handshake: ~100ms
TLS 1.3 Handshake: ~50ms
Result: 50% faster connection establishment

AES-256: Unbreakable Encryption

Advanced Encryption Standard with 256-bit keys is the gold standard for symmetric encryption:

  • Key Length: 256 bits (2^256 possible combinations)

  • Block Size: 128 bits

  • Rounds: 14 encryption rounds

  • Security Level: Approved for TOP SECRET information by NSA


Frontend Security: React Implementation

Setting Up HTTPS and TLS 1.3

First, let's configure your React development environment for secure communication:

package.json Configuration:

{
  "name": "secure-react-app",
  "scripts": {
    "start": "HTTPS=true SSL_CRT_FILE=./certs/localhost.crt SSL_KEY_FILE=./certs/localhost.key react-scripts start",
    "build": "react-scripts build"
  },
  "dependencies": {
    "react": "^18.2.0",
    "axios": "^1.4.0",
    "crypto-js": "^4.1.1"
  }
}

Environment Configuration (.env):

HTTPS=true
REACT_APP_API_BASE_URL=https://api.yourapp.com
REACT_APP_ENCRYPTION_ENABLED=true
SSL_CRT_FILE=./certs/localhost.crt
SSL_KEY_FILE=./certs/localhost.key

Implementing Client-Side Encryption

Create a secure encryption service for sensitive data:

services/EncryptionService.js:

import CryptoJS from 'crypto-js';

class EncryptionService {
  constructor() {
    this.algorithm = 'AES-256-GCM';
    this.keySize = 256;
    this.ivSize = 96; // 12 bytes for GCM
    this.tagSize = 128; // 16 bytes
  }

  // Generate a secure encryption key
  generateKey() {
    return CryptoJS.lib.WordArray.random(this.keySize / 8).toString();
  }

  // Encrypt data using AES-256-GCM
  encrypt(plaintext, key) {
    try {
      const iv = CryptoJS.lib.WordArray.random(this.ivSize / 8);
      const encrypted = CryptoJS.AES.encrypt(plaintext, key, {
        iv: iv,
        mode: CryptoJS.mode.GCM,
        padding: CryptoJS.pad.NoPadding
      });

      return {
        ciphertext: encrypted.ciphertext.toString(),
        iv: iv.toString(),
        tag: encrypted.tag?.toString() || ''
      };
    } catch (error) {
      console.error('Encryption failed:', error);
      throw new Error('Data encryption failed');
    }
  }

  // Decrypt data using AES-256-GCM
  decrypt(encryptedData, key) {
    try {
      const decrypted = CryptoJS.AES.decrypt(
        {
          ciphertext: CryptoJS.enc.Hex.parse(encryptedData.ciphertext),
          tag: CryptoJS.enc.Hex.parse(encryptedData.tag)
        },
        key,
        {
          iv: CryptoJS.enc.Hex.parse(encryptedData.iv),
          mode: CryptoJS.mode.GCM,
          padding: CryptoJS.pad.NoPadding
        }
      );

      return decrypted.toString(CryptoJS.enc.Utf8);
    } catch (error) {
      console.error('Decryption failed:', error);
      throw new Error('Data decryption failed');
    }
  }
}

export default new EncryptionService();

Secure API Communication

Implement secure HTTP client with proper TLS configuration:

services/ApiService.js:

import axios from 'axios';
import EncryptionService from './EncryptionService';

class ApiService {
  constructor() {
    this.client = axios.create({
      baseURL: process.env.REACT_APP_API_BASE_URL,
      timeout: 30000,
      headers: {
        'Content-Type': 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
      },
    });

    this.setupInterceptors();
  }

  setupInterceptors() {
    // Request interceptor for authentication and encryption
    this.client.interceptors.request.use(
      (config) => {
        // Add authentication token
        const token = this.getAuthToken();
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }

        // Encrypt sensitive data
        if (config.data && this.shouldEncrypt(config.url)) {
          const encryptionKey = this.getEncryptionKey();
          config.data = {
            encryptedData: EncryptionService.encrypt(
              JSON.stringify(config.data),
              encryptionKey
            ),
            encrypted: true
          };
        }

        return config;
      },
      (error) => Promise.reject(error)
    );

    // Response interceptor for decryption and error handling
    this.client.interceptors.response.use(
      (response) => {
        // Decrypt response if needed
        if (response.data?.encrypted) {
          const encryptionKey = this.getEncryptionKey();
          const decryptedData = EncryptionService.decrypt(
            response.data.encryptedData,
            encryptionKey
          );
          response.data = JSON.parse(decryptedData);
        }
        return response;
      },
      (error) => {
        this.handleApiError(error);
        return Promise.reject(error);
      }
    );
  }

  getAuthToken() {
    return sessionStorage.getItem('authToken'); // Avoid localStorage for tokens
  }

  getEncryptionKey() {
    return sessionStorage.getItem('encryptionKey');
  }

  shouldEncrypt(url) {
    const encryptedEndpoints = ['/api/users', '/api/payments', '/api/sensitive-data'];
    return encryptedEndpoints.some(endpoint => url.includes(endpoint));
  }

  handleApiError(error) {
    if (error.response?.status === 401) {
      // Handle unauthorized access
      this.logout();
    }
    console.error('API Error:', error.response?.data || error.message);
  }

  logout() {
    sessionStorage.clear();
    window.location.href = '/login';
  }
}

export default new ApiService();

Secure Component Implementation

Example of a secure form component with encryption:

components/SecureForm.jsx:

import React, { useState } from 'react';
import ApiService from '../services/ApiService';
import EncryptionService from '../services/EncryptionService';

const SecureForm = () => {
  const [formData, setFormData] = useState({
    email: '',
    creditCard: '',
    ssn: ''
  });
  const [loading, setLoading] = useState(false);
  const [errors, setErrors] = useState({});

  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: value
    }));
    
    // Clear error when user starts typing
    if (errors[name]) {
      setErrors(prev => ({
        ...prev,
        [name]: ''
      }));
    }
  };

  const validateForm = () => {
    const newErrors = {};
    
    if (!formData.email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) {
      newErrors.email = 'Invalid email format';
    }
    
    if (!formData.creditCard.match(/^\d{16}$/)) {
      newErrors.creditCard = 'Credit card must be 16 digits';
    }
    
    if (!formData.ssn.match(/^\d{3}-\d{2}-\d{4}$/)) {
      newErrors.ssn = 'SSN must be in format XXX-XX-XXXX';
    }
    
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    if (!validateForm()) {
      return;
    }

    setLoading(true);
    
    try {
      // Submit encrypted data
      const response = await ApiService.client.post('/api/users/secure-data', {
        email: formData.email,
        creditCard: formData.creditCard,
        ssn: formData.ssn
      });
      
      console.log('Data submitted successfully:', response.data);
      
      // Clear form
      setFormData({
        email: '',
        creditCard: '',
        ssn: ''
      });
      
      alert('Data submitted successfully!');
    } catch (error) {
      console.error('Submission failed:', error);
      alert('Submission failed. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="secure-form-container">
      <h2>Secure Data Entry Form</h2>
      <form onSubmit={handleSubmit} className="secure-form">
        <div className="form-group">
          <label htmlFor="email">Email:</label>
          <input
            type="email"
            id="email"
            name="email"
            value={formData.email}
            onChange={handleInputChange}
            required
            autoComplete="off"
          />
          {errors.email && <span className="error">{errors.email}</span>}
        </div>

        <div className="form-group">
          <label htmlFor="creditCard">Credit Card:</label>
          <input
            type="password"
            id="creditCard"
            name="creditCard"
            value={formData.creditCard}
            onChange={handleInputChange}
            placeholder="1234567890123456"
            maxLength="16"
            required
            autoComplete="off"
          />
          {errors.creditCard && <span className="error">{errors.creditCard}</span>}
        </div>

        <div className="form-group">
          <label htmlFor="ssn">SSN:</label>
          <input
            type="password"
            id="ssn"
            name="ssn"
            value={formData.ssn}
            onChange={handleInputChange}
            placeholder="123-45-6789"
            maxLength="11"
            required
            autoComplete="off"
          />
          {errors.ssn && <span className="error">{errors.ssn}</span>}
        </div>

        <button type="submit" disabled={loading} className="submit-button">
          {loading ? 'Submitting...' : 'Submit Securely'}
        </button>
      </form>
    </div>
  );
};

export default SecureForm;

Backend Security: .NET Core Microservices

TLS 1.3 Configuration

Configure your ASP.NET Core application for TLS 1.3:

Program.cs:

using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

var builder = WebApplication.CreateBuilder(args);

// Configure Kestrel for TLS 1.3
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(httpsOptions =>
    {
        httpsOptions.SslProtocols = SslProtocols.Tls13;
        httpsOptions.ClientCertificateMode = ClientCertificateMode.NoCertificate;
        httpsOptions.CheckCertificateRevocation = true;
        
        // Load certificate from configuration
        var certPath = builder.Configuration["Https:Certificate:Path"];
        var certPassword = builder.Configuration["Https:Certificate:Password"];
        
        if (!string.IsNullOrEmpty(certPath))
        {
            httpsOptions.ServerCertificate = new X509Certificate2(certPath, certPassword);
        }
    });
    
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024 * 1024; // 10MB
});

// Add services
builder.Services.AddControllers();
builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
    options.HttpsPort = 443;
});

// Add custom services
builder.Services.AddScoped<IEncryptionService, EncryptionService>();
builder.Services.AddScoped<IKeyManagementService, KeyManagementService>();

// Security headers middleware
builder.Services.AddHeaderSecurity();

var app = builder.Build();

// Configure pipeline
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseSecurityHeaders();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

app.Run();

AES-256 Encryption Service

Implement a robust encryption service:

Services/EncryptionService.cs:

using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

public interface IEncryptionService
{
    Task<EncryptedData> EncryptAsync(string plaintext, string key);
    Task<string> DecryptAsync(EncryptedData encryptedData, string key);
    string GenerateKey();
}

public class EncryptedData
{
    public string Ciphertext { get; set; } = string.Empty;
    public string IV { get; set; } = string.Empty;
    public string Tag { get; set; } = string.Empty;
}

public class EncryptionService : IEncryptionService
{
    private const int KeySize = 256; // AES-256
    private const int IVSize = 12;   // 96 bits for GCM
    private const int TagSize = 16;  // 128 bits

    public async Task<EncryptedData> EncryptAsync(string plaintext, string key)
    {
        if (string.IsNullOrEmpty(plaintext))
            throw new ArgumentException("Plaintext cannot be null or empty", nameof(plaintext));
        
        if (string.IsNullOrEmpty(key))
            throw new ArgumentException("Key cannot be null or empty", nameof(key));

        using var aes = new AesGcm(Convert.FromBase64String(key));
        
        var plaintextBytes = Encoding.UTF8.GetBytes(plaintext);
        var ciphertext = new byte[plaintextBytes.Length];
        var iv = new byte[IVSize];
        var tag = new byte[TagSize];

        // Generate random IV
        RandomNumberGenerator.Fill(iv);

        // Encrypt
        aes.Encrypt(iv, plaintextBytes, ciphertext, tag);

        return new EncryptedData
        {
            Ciphertext = Convert.ToBase64String(ciphertext),
            IV = Convert.ToBase64String(iv),
            Tag = Convert.ToBase64String(tag)
        };
    }

    public async Task<string> DecryptAsync(EncryptedData encryptedData, string key)
    {
        if (encryptedData == null)
            throw new ArgumentNullException(nameof(encryptedData));
        
        if (string.IsNullOrEmpty(key))
            throw new ArgumentException("Key cannot be null or empty", nameof(key));

        try
        {
            using var aes = new AesGcm(Convert.FromBase64String(key));
            
            var ciphertext = Convert.FromBase64String(encryptedData.Ciphertext);
            var iv = Convert.FromBase64String(encryptedData.IV);
            var tag = Convert.FromBase64String(encryptedData.Tag);
            var plaintext = new byte[ciphertext.Length];

            // Decrypt
            aes.Decrypt(iv, ciphertext, tag, plaintext);

            return Encoding.UTF8.GetString(plaintext);
        }
        catch (Exception ex)
        {
            throw new CryptographicException("Decryption failed", ex);
        }
    }

    public string GenerateKey()
    {
        var key = new byte[KeySize / 8]; // 32 bytes for AES-256
        RandomNumberGenerator.Fill(key);
        return Convert.ToBase64String(key);
    }
}

Key Management Service

Implement secure key management:

Services/KeyManagementService.cs:

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;

public interface IKeyManagementService
{
    Task<string> GetEncryptionKeyAsync(string keyName);
    Task StoreEncryptionKeyAsync(string keyName, string key);
    Task<string> RotateKeyAsync(string keyName);
}

public class KeyManagementService : IKeyManagementService
{
    private readonly SecretClient _secretClient;
    private readonly IEncryptionService _encryptionService;
    private readonly ILogger<KeyManagementService> _logger;

    public KeyManagementService(
        IConfiguration configuration,
        IEncryptionService encryptionService,
        ILogger<KeyManagementService> logger)
    {
        var keyVaultUrl = configuration["KeyVault:Url"];
        _secretClient = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential());
        _encryptionService = encryptionService;
        _logger = logger;
    }

    public async Task<string> GetEncryptionKeyAsync(string keyName)
    {
        try
        {
            var secret = await _secretClient.GetSecretAsync(keyName);
            return secret.Value.Value;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to retrieve encryption key: {KeyName}", keyName);
            throw;
        }
    }

    public async Task StoreEncryptionKeyAsync(string keyName, string key)
    {
        try
        {
            await _secretClient.SetSecretAsync(keyName, key);
            _logger.LogInformation("Encryption key stored successfully: {KeyName}", keyName);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to store encryption key: {KeyName}", keyName);
            throw;
        }
    }

    public async Task<string> RotateKeyAsync(string keyName)
    {
        try
        {
            var newKey = _encryptionService.GenerateKey();
            await StoreEncryptionKeyAsync($"{keyName}-new", newKey);
            
            // In production, implement gradual key rotation
            // Keep old key for decryption, use new key for encryption
            
            _logger.LogInformation("Key rotated successfully: {KeyName}", keyName);
            return newKey;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to rotate key: {KeyName}", keyName);
            throw;
        }
    }
}

Secure API Controller

Example controller with encryption middleware:

Controllers/SecureDataController.cs:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
[Authorize]
public class SecureDataController : ControllerBase
{
    private readonly IEncryptionService _encryptionService;
    private readonly IKeyManagementService _keyManagement;
    private readonly ILogger<SecureDataController> _logger;

    public SecureDataController(
        IEncryptionService encryptionService,
        IKeyManagementService keyManagement,
        ILogger<SecureDataController> logger)
    {
        _encryptionService = encryptionService;
        _keyManagement = keyManagement;
        _logger = logger;
    }

    [HttpPost("submit")]
    public async Task<IActionResult> SubmitSecureData([FromBody] SecureDataRequest request)
    {
        try
        {
            // Validate request
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            // Get encryption key
            var encryptionKey = await _keyManagement.GetEncryptionKeyAsync("user-data-key");

            // Decrypt incoming data if encrypted
            if (request.Encrypted)
            {
                var decryptedData = await _encryptionService.DecryptAsync(request.EncryptedData, encryptionKey);
                request = JsonSerializer.Deserialize<SecureDataRequest>(decryptedData);
            }

            // Process the secure data
            var result = await ProcessSecureData(request);

            // Encrypt response if needed
            var response = new SecureDataResponse
            {
                Success = true,
                Message = "Data processed successfully",
                Data = result
            };

            // Return encrypted response
            var encryptedResponse = await _encryptionService.EncryptAsync(
                JsonSerializer.Serialize(response),
                encryptionKey
            );

            return Ok(new { EncryptedData = encryptedResponse, Encrypted = true });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing secure data");
            return StatusCode(500, new { Message = "Internal server error" });
        }
    }

    private async Task<object> ProcessSecureData(SecureDataRequest request)
    {
        // Implement your business logic here
        // This is where you would save to database, call other services, etc.
        
        _logger.LogInformation("Processing secure data for user");
        
        return new
        {
            ProcessedAt = DateTime.UtcNow,
            Status = "Completed"
        };
    }
}

public class SecureDataRequest
{
    public string Email { get; set; } = string.Empty;
    public string CreditCard { get; set; } = string.Empty;
    public string SSN { get; set; } = string.Empty;
    public bool Encrypted { get; set; }
    public EncryptedData? EncryptedData { get; set; }
}

public class SecureDataResponse
{
    public bool Success { get; set; }
    public string Message { get; set; } = string.Empty;
    public object? Data { get; set; }
}

Database Security: PostgreSQL Encryption

PostgreSQL TLS Configuration

Configure PostgreSQL for secure connections:

postgresql.conf:

# Connection Settings
listen_addresses = '*'
port = 5432
max_connections = 200

# TLS/SSL Settings
ssl = on
ssl_cert_file = '/var/lib/postgresql/server.crt'
ssl_key_file = '/var/lib/postgresql/server.key'
ssl_ca_file = '/var/lib/postgresql/root.crt'
ssl_protocols = 'TLSv1.3'
ssl_ciphers = 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384'
ssl_prefer_server_ciphers = on
ssl_ecdh_curve = 'prime256v1'

# Security Settings
password_encryption = scram-sha-256
log_connections = on
log_disconnections = on
log_statement = 'all'

# Performance with Security
shared_preload_libraries = 'pg_stat_statements'

pg_hba.conf:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             postgres                                peer
hostssl all             all             0.0.0.0/0              scram-sha-256
hostssl all             all             ::/0                   scram-sha-256

Database Connection with TLS

Configure secure database connections in .NET Core:

appsettings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Host=localhost;Port=5432;Database=secureapp;Username=appuser;Password=strongpassword;SSL Mode=Require;Trust Server Certificate=false;Include Error Detail=true;Timeout=30;Command Timeout=30"
  },
  "DatabaseSecurity": {
    "EncryptSensitiveColumns": true,
    "EncryptionKeyName": "db-encryption-key"
  }
}

Column-Level Encryption

Implement transparent column encryption:

Models/EncryptedUser.cs:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

public class User
{
    [Key]
    public int Id { get; set; }
    
    [Required]
    [EmailAddress]
    public string Email { get; set; } = string.Empty;
    
    [Encrypted]
    public string? CreditCard { get; set; }
    
    [Encrypted]
    public string? SSN { get; set; }
    
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}

[AttributeUsage(AttributeTargets.Property)]
public class EncryptedAttribute : Attribute
{
}

Data/EncryptionInterceptor.cs:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Reflection;

public class EncryptionInterceptor : SaveChangesInterceptor
{
    private readonly IEncryptionService _encryptionService;
    private readonly IKeyManagementService _keyManagement;

    public EncryptionInterceptor(
        IEncryptionService encryptionService,
        IKeyManagementService keyManagement)
    {
        _encryptionService = encryptionService;
        _keyManagement = keyManagement;
    }

    public override async ValueTask<InterceptionResult<int>> SavingChangesAsync(
        DbContextEventData eventData,
        InterceptionResult<int> result,
        CancellationToken cancellationToken = default)
    {
        if (eventData.Context != null)
        {
            await EncryptEntities(eventData.Context);
        }

        return await base.SavingChangesAsync(eventData, result, cancellationToken);
    }

    private async Task EncryptEntities(DbContext context)
    {
        var encryptionKey = await _keyManagement.GetEncryptionKeyAsync("db-encryption-key");
        
        var entities = context.ChangeTracker.Entries()
            .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
            .ToList();

        foreach (var entity in entities)
        {
            var properties = entity.Entity.GetType().GetProperties()
                .Where(p => p.GetCustomAttribute<EncryptedAttribute>() != null);

            foreach (var property in properties)
            {
                var value = property.GetValue(entity.Entity) as string;
                if (!string.IsNullOrEmpty(value) && !IsAlreadyEncrypted(value))
                {
                    var encryptedData = await _encryptionService.EncryptAsync(value, encryptionKey);
                    var encryptedValue = System.Text.Json.JsonSerializer.Serialize(encryptedData);
                    property.SetValue(entity.Entity, encryptedValue);
                }
            }
        }
    }

    private bool IsAlreadyEncrypted(string value)
    {
        try
        {
            System.Text.Json.JsonSerializer.Deserialize<EncryptedData>(value);
            return true;
        }
        catch
        {
            return false;
        }
    }
}

Data/ApplicationDbContext.cs:

using Microsoft.EntityFrameworkCore;

public class ApplicationDbContext : DbContext
{
    private readonly IEncryptionService _encryptionService;
    private readonly IKeyManagementService _keyManagement;

    public ApplicationDbContext(
        DbContextOptions<ApplicationDbContext> options,
        IEncryptionService encryptionService,
        IKeyManagementService keyManagement) : base(options)
    {
        _encryptionService = encryptionService;
        _keyManagement = keyManagement;
    }

    public DbSet<User> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.AddInterceptors(new EncryptionInterceptor(_encryptionService, _keyManagement));
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Configure entity mappings
        modelBuilder.Entity<User>(entity =>
        {

More from FlexiDigit Blogs