Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

2 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿฐ Bastion โ€” Enterprise Authentication & Security System

.NET 10 C# SQL Server License Build Security


Description

Bastion is a production-ready authentication and security monitoring API built with ASP.NET Core 10. It goes beyond traditional login systems by actively detecting and logging security threats in real time โ€” including honeytoken access, impossible travel anomalies, decoy endpoint probing, and SQL injection attempts.

Traditional auth systems silently succeed or fail. Bastion gives security teams visibility into who is attacking, how they're attacking, and where they're coming from โ€” all surfaced through a live dashboard with geographical mapping and health monitoring.


Features

Icon Feature Details
๐Ÿ” BCrypt + JWT Authentication Password hashing with BCrypt, stateless JWT tokens (HS256, 24h expiry)
๐Ÿ›ก๏ธ SQL Injection Detection 7 regex patterns blocking tautologies, UNION, DDL, comments, stacked queries
๐Ÿšจ Canary/Honeytoken Account Fake administrator account; any login attempt triggers CANARY_TRIGGERED
โœˆ๏ธ Impossible Travel Detection Haversine distance calculation; flags logins >900 km/h between successive locations
๐ŸŽฏ Decoy Endpoints /api/admin/export-users, /.env, /api/backup/download โ†’ 404 + DECOY_TRIGGERED
๐Ÿ—บ๏ธ Live Attack Map Leaflet.js map with color-coded markers (red = threat, blue = normal)
๐Ÿ“Š Health Gauge Circular gauge โ€” green (safe), yellow pulse (1-2 threats), red pulse (3+)
๐ŸŽฎ Demo Mode One-click attack simulation: 6 failed logins + canary touch + 2 impossible-travel logins
๐Ÿ”’ Rate Limiting & Lockout 10 req/15min sliding window per IP; 5 failed attempts = 30min account lockout
๐ŸŒ GeoIP Resolution MaxMind GeoIP2 integration for Country/City location on every login

Architecture Overview

Bastion follows Clean Architecture principles with the Repository Pattern:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   Controllers (API)                   โ”‚
โ”‚  AuthController ยท DemoController                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                   Services (Business Logic)           โ”‚
โ”‚  AuthService ยท SecurityPatterns                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚              Interfaces (Abstractions)                โ”‚
โ”‚  IRepository<T> ยท IAuthService                        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚              Data (Persistence)                       โ”‚
โ”‚  SqlRepository<T> ยท AppDbContext ยท JsonRepository     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚              Models (Domain)                          โ”‚
โ”‚  User ยท LoginAttempt                                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Why this approach?

  • Database-agnostic โ€” Swap SQL Server for PostgreSQL, MySQL, or JSON files by changing only the Data layer
  • Testable โ€” Inject mock repositories into services for unit testing
  • Maintainable โ€” Clear separation of concerns; each layer has a single responsibility
  • Security-first โ€” Validation at controller and service layers (defense in depth)

Tech Stack

Layer Technology
Backend C# 12 / .NET 10
Framework ASP.NET Core Web API
Database SQL Server + Entity Framework Core 10
Authentication BCrypt.Net-Next + JWT (System.IdentityModel.Tokens.Jwt)
GeoIP MaxMind.GeoIP2 6.0
Logging Serilog (console + rolling file)
Frontend HTML5 / CSS3 / Vanilla JS
Map Leaflet.js 1.9 + OpenStreetMap tiles
Database Migrations EF Core Migrations

Quick Start Guide

Prerequisites

Setup

# Clone the repository
git clone https://github.com/AbdullahAlHadabi/Bastion.git
cd Bastion

# Restore dependencies
dotnet restore

# Create the database and apply migrations
dotnet ef database update

# Initialize user secrets (required for JWT key and DemoMode)
dotnet user-secrets init
dotnet user-secrets set "Jwt:Key" "YourSuperSecretKeyHere123!@#"
dotnet user-secrets set "DemoMode" "true"

# Run the application
dotnet run --urls http://localhost:5000

# (Optional) Download GeoIP database for real IP lookups:
# Place GeoLite2-City.mmdb in the Data/ folder
# https://dev.maxmind.com/geoip/geolite2-free-geolocation-data

Note: DemoMode must be "true" (string, not boolean) and the environment must be Development for user-secrets to load.

$env:ASPNETCORE_ENVIRONMENT = "Development"

Verify It Works

# Health check
curl http://localhost:5000/

# Register a user
curl -X POST http://localhost:5000/api/auth/register \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"demo\",\"password\":\"Demo@123\"}"

# Login
curl -X POST http://localhost:5000/api/auth/login \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"demo\",\"password\":\"Demo@123\"}"

# Open the dashboard
start http://localhost:5000/dashboard.html

# Simulate an attack
curl -X POST http://localhost:5000/api/demo/simulate-attack

API Endpoints

Authentication

POST /api/auth/register

Register a new user account.

// Request
{ "username": "johndoe", "password": "P@ssw0rd!" }

// Response 201 Created
{ "message": "Registration successful." }

// Response 409 Conflict
{ "message": "Username already exists." }

// Response 400 Bad Request (SQL injection detected)
{ "message": "Invalid input detected." }

POST /api/auth/login

Authenticate and receive a JWT token.

// Request
{ "username": "johndoe", "password": "P@ssw0rd!" }

// Response 200 OK
{ "token": "eyJhbGciOiJIUzI1NiIs...", "message": "Login successful." }

// Response 401 Unauthorized
{ "message": "Invalid credentials." }

// Response 429 Too Many Requests (rate limited)
{ "message": "Rate limit exceeded. Try again later." }

Monitoring

GET /api/auth/attempts

Returns the last 100 login attempts (ordered newest first).

// Response 200 OK
[
  {
    "id": 42,
    "username": "johndoe",
    "success": true,
    "ipAddress": "51.5074.0.1",
    "eventType": "NORMAL",
    "country": "United Kingdom",
    "city": "London",
    "latitude": 51.5074,
    "longitude": -0.1278,
    "timestamp": "2026-07-10T20:00:00Z"
  }
]

GET /api/auth/active-sessions

Returns distinct usernames with successful logins in the last 24 hours.

// Response 200 OK
["johndoe", "traveluser", "verify_user"]

Demo / Security Testing

POST /api/demo/simulate-attack

Runs a background attack simulation (requires DemoMode=true). Performs:

  • 6 failed login attempts (random IPs)
  • 1 canary account touch (CANARY_TRIGGERED)
  • 2 distant successful logins (IMPOSSIBLE_TRAVEL)
// Response 200 OK
{ "message": "Attack simulation started. Check logs for details." }

// Response 403 Forbidden (DemoMode disabled)
{ "message": "Demo mode is disabled." }

Decoy Endpoints (Honeypots)

These endpoints return 404 Not Found and log DECOY_TRIGGERED:

Endpoint Purpose
GET /api/admin/export-users Mimics data exfiltration
GET /.env Mimics environment file scraping
GET /api/backup/download Mimics backup download

Event Types

Event Type Severity Description
NORMAL โœ… Info Standard successful or failed login
CANARY_TRIGGERED ๐Ÿ”ด Critical Honeytoken administrator account was accessed
IMPOSSIBLE_TRAVEL ๐Ÿ”ด Critical User logged in from two distant locations faster than physically possible (>900 km/h)
DECOY_TRIGGERED ๐ŸŸก Warning Decoy endpoint was probed by an attacker

Database Schema

Users

Column Type Constraints
Id int PK, Identity
Username nvarchar(max) NOT NULL
PasswordHash nvarchar(max) NOT NULL
Role nvarchar(max) NOT NULL ("User" or "Admin")
FailedAttempts int NOT NULL
LockedUntil datetime2 NULL
LastLoginLat float NULL
LastLoginLon float NULL
LastLoginAt datetime2 NULL
CreatedAt datetime2 NOT NULL

LoginAttempts

Column Type Constraints
Id int PK, Identity
Username nvarchar(max) NOT NULL
Success bit NOT NULL
IpAddress nvarchar(max) NOT NULL
EventType nvarchar(max) NOT NULL
FailureReason nvarchar(max) NULL
Country nvarchar(max) NULL
City nvarchar(max) NULL
Latitude float NULL
Longitude float NULL
Timestamp datetime2 NOT NULL

Dashboard Features

The live security dashboard is served at /dashboard.html and features:

Component Description
๐Ÿ—บ๏ธ Live Attack Map Leaflet.js map with red markers for threats, blue for normal; auto-fits bounds
๐Ÿ“Š Health Gauge Circular gauge with breathing animation: ๐ŸŸข Green (0 threats), ๐ŸŸก Yellow pulse (1-2), ๐Ÿ”ด Red pulse (3+)
๐Ÿšจ Threat Alerts Scrollable list of non-normal events with color-coded left border (red = threat, blue = normal)
๐Ÿ“‹ Recent Attempts Table showing last 50 attempts with time, username, IP, location, event type, and status
๐Ÿ”„ Auto-Refresh Polls every 3 seconds for new data
๐ŸŽฎ Simulate Attack One-click button triggers the full attack simulation

Dashboard Screenshot

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  BASTION SECURITY DASHBOARD         [Simulate Attack]   โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                โ”‚
โ”‚  โ”‚ Threats  โ”‚ โ”‚ Attempts โ”‚ โ”‚ Sessions โ”‚                โ”‚
โ”‚  โ”‚    3     โ”‚ โ”‚    39    โ”‚ โ”‚    4     โ”‚                โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚    Live Attack Map      โ”‚ โ”‚   Health Gauge       โ”‚  โ”‚
โ”‚  โ”‚    [Leaflet Map]        โ”‚ โ”‚      โ— [3]           โ”‚  โ”‚
โ”‚  โ”‚    โ— Red (New York)     โ”‚ โ”‚    (Red pulsing)     โ”‚  โ”‚
โ”‚  โ”‚    โ— Blue (London)      โ”‚ โ”‚                      โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚  Threat Alerts                                   โ”‚  โ”‚
โ”‚  โ”‚  ๐Ÿ”ด IMPOSSIBLE_TRAVEL โ€” traveluser @ NY (20:09) โ”‚  โ”‚
โ”‚  โ”‚  ๐Ÿ”ด CANARY_TRIGGERED โ€” administrator @ 10.0.0.1 โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚  Recent Attempts                                 โ”‚  โ”‚
โ”‚  โ”‚  Time  โ”‚ User    โ”‚ IP      โ”‚ Location  โ”‚ Event   โ”‚  โ”‚
โ”‚  โ”‚  20:09 โ”‚ travel  โ”‚ 40.71.. โ”‚ NY, USA   โ”‚ IMPOS.. โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Testing

Verified Endpoints

Test Endpoint Expected Status
Root health check GET / 200 OK โœ…
Register new user POST /api/auth/register 201 Created โœ…
Register duplicate POST /api/auth/register 409 Conflict โœ…
SQL injection (tautology) POST /api/auth/register 400 Bad Request โœ…
SQL injection (DROP TABLE) POST /api/auth/register 400 Bad Request โœ…
Valid login POST /api/auth/login 200 OK + JWT โœ…
Wrong password POST /api/auth/login 401 Unauthorized โœ…
Wrong username POST /api/auth/login 401 Unauthorized โœ…
Rate limiting POST /api/auth/login 429 Too Many Requests โœ…
Account lockout (5 fails) POST /api/auth/login 401 + locked โœ…
Get attempts GET /api/auth/attempts 200 OK โœ…
Active sessions GET /api/auth/active-sessions 200 OK โœ…
Canary trigger Login as administrator CANARY_TRIGGERED โœ…
Impossible travel London โ†’ New York IMPOSSIBLE_TRAVEL โœ…
Attack simulation POST /api/demo/simulate-attack 200 OK โœ…
Decoy endpoints GET /api/admin/export-users 404 + DECOY_TRIGGERED โœ…
Dashboard GET /dashboard.html 200 OK โœ…

Running Tests

# Manual API tests with curl
curl http://localhost:5000/
curl -X POST http://localhost:5000/api/auth/register -H "Content-Type: application/json" -d "{\"username\":\"test\",\"password\":\"Test@123\"}"
curl -X POST http://localhost:5000/api/auth/login -H "Content-Type: application/json" -d "{\"username\":\"test\",\"password\":\"Test@123\"}"

# Check database directly (PowerShell + SqlServer module or SSMS)
Invoke-Sqlcmd -Query "SELECT EventType, COUNT(*) as Count FROM LoginAttempts GROUP BY EventType" -ServerInstance "localhost" -Database "BastionDb"

Project Structure

Bastion/
โ”œโ”€โ”€ Controllers/
โ”‚   โ”œโ”€โ”€ AuthController.cs          # Register, Login, attempts, sessions
โ”‚   โ””โ”€โ”€ DemoController.cs          # Attack simulation, decoy endpoints
โ”œโ”€โ”€ Services/
โ”‚   โ””โ”€โ”€ AuthService.cs             # Business logic: auth, GeoIP, impossible travel
โ”œโ”€โ”€ Interfaces/
โ”‚   โ””โ”€โ”€ IRepository.cs             # Generic repository contract
โ”œโ”€โ”€ Data/
โ”‚   โ”œโ”€โ”€ AppDbContext.cs            # EF Core DbContext
โ”‚   โ”œโ”€โ”€ SqlRepository.cs           # SQL Server implementation
โ”‚   โ”œโ”€โ”€ JsonFileContext.cs         # JSON file implementation (legacy)
โ”‚   โ”œโ”€โ”€ JsonRepository.cs          # JSON file repository
โ”‚   โ””โ”€โ”€ DesignTimeDbContextFactory.cs
โ”œโ”€โ”€ Models/
โ”‚   โ”œโ”€โ”€ User.cs                    # User entity
โ”‚   โ””โ”€โ”€ LoginAttempt.cs            # Login attempt entity
โ”œโ”€โ”€ Security/
โ”‚   โ””โ”€โ”€ SecurityPatterns.cs        # SQL injection regex detection
โ”œโ”€โ”€ Migrations/                    # EF Core migrations
โ”œโ”€โ”€ wwwroot/
โ”‚   โ””โ”€โ”€ dashboard.html             # Live security dashboard
โ”œโ”€โ”€ Program.cs                     # App startup, DI, middleware
โ”œโ”€โ”€ appsettings.json               # Configuration (connection string, etc.)
โ”œโ”€โ”€ appsettings.Development.json   # Development overrides
โ”œโ”€โ”€ Bastion.csproj                 # Project file
โ”œโ”€โ”€ Properties/
โ”‚   โ””โ”€โ”€ launchSettings.json        # Launch profiles
โ””โ”€โ”€ Data/
    โ””โ”€โ”€ GeoLite2-City.mmdb         # MaxMind GeoIP database (download separately)

Security Features in Depth

Rate Limiting

  • Window: 10 requests per 15-minute sliding window
  • Scope: Per IP address
  • Implementation: In-memory ConcurrentDictionary<string, List<DateTime>> with lock-free reads

Account Lockout

  • Threshold: 5 failed attempts
  • Duration: 30 minutes
  • Reset: Successful login resets the counter

SQL Injection Detection

Input is validated at both the controller layer (AuthController.ContainsSqlInjection) and the service layer (SecurityPatterns.IsMalicious) for defense in depth.

Seven regex patterns are checked against both username and password fields on every register and login request:

// SQL Injection Detection โ€” 7 Regex Patterns
private bool ContainsSqlInjection(string input)
{
    var patterns = new[]
    {
        @"(\b(OR|AND)\b\s*['""]?\d+['""]?\s*=\s*['""]?\d+['""]?)", // Tautology
        @"UNION\s+SELECT",                                     // Union
        @"\b(DROP|ALTER|EXEC|EXECUTE)\b",                     // DDL
        @"--",                                                // Inline comment
        @"\/\*.*\*\/",                                        // Block comment
        @";\s*(DROP|SELECT|INSERT)",                          // Stacked queries
        @"\bOR\b\s+.*\bOR\b"                                  // Chained OR
    };
    return patterns.Any(p => Regex.IsMatch(input, p, RegexOptions.IgnoreCase));
}
# Pattern Targets Example Blocked
1 Tautology OR/AND with numeric comparison ' OR '1'='1
2 Union UNION SELECT ' UNION SELECT * FROM Users
3 DDL DROP, ALTER, EXEC, EXECUTE ' DROP TABLE Users --
4 Inline comment -- admin'--
5 Block comment /* */ '/**/OR/**/1=1--
6 Stacked queries ; followed by SQL '; DROP TABLE Users --
7 Chained OR Two or more OR clauses ' OR 'a'='a' OR 'b'='b

When a match is found, the API returns 400 Bad Request with {"message":"Invalid input detected."} โ€” the request is rejected before reaching any database operation.

Canary Account

  • Pre-seeded administrator account with a random 128-char password
  • Any login attempt โ†’ CANARY_TRIGGERED event
  • Password is intentionally unknown (generated with Guid.NewGuid())

Impossible Travel Detection

  • Algorithm: Haversine formula for great-circle distance
  • Threshold: >900 km/h (roughly commercial aircraft speed)
  • Resolution: Demo IPs (51.5074.0.1 = London, 40.7128.0.1 = New York) or real MaxMind GeoIP2
  • Verification: Travel from London to New York in <5 seconds โ†’ detected

Lessons Learned

๐Ÿ—๏ธ Dependency Inversion in Practice

Using IRepository<T> meant we could swap JSON file storage for SQL Server without changing a single line of service code. The same interface supports both JsonRepository and SqlRepository โ€” proving that Clean Architecture pays off in real projects.

๐Ÿ”’ Security-First Mindset

Security isn't a feature โ€” it's an architectural concern. Validating input at the controller and service layer (defense in depth), rate-limiting before auth checks, and logging every attempt (not just failures) are patterns every auth system should follow.

๐Ÿ“Š Real-Time Feedback Matters

The 3-second polling dashboard turned abstract events (log entries) into an engaging visual experience. Security teams can spot attack patterns at a glance โ€” the map makes impossible travel immediately obvious.

๐ŸŽฎ Safe Demos with Feature Flags

The DemoMode flag (stored in user-secrets) keeps demo functionality isolated. Attack simulations run in background tasks with their own DI scopes, preventing side effects like disposed DbContext errors.


License

This project is licensed under the MIT License โ€” see the LICENSE file for details.

MIT License

Copyright (c) 2026 Abdullah Al-Hadabi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

Contributors & Acknowledgments

Author

  • Abdullah Al-Hadabi โ€” Full-stack security engineer and project architect

Acknowledgments

  • MaxMind for the GeoLite2 free geolocation database
  • Leaflet.js for the open-source mapping library
  • OpenStreetMap for tile services
  • BCrypt.Net for reliable password hashing
  • Serilog for structured logging
  • The ASP.NET Core team for the robust web framework

Technologies Used


Built with ๐Ÿ”ด by Abdullah Al-Hadabi
Because security shouldn't be invisible.

About

๐Ÿฐ Bastion โ€” Enterprise Authentication & Security System

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages