← Portfolio / Case Study
Cybersecurity Node.js React MongoDB JWT · MFA · RBAC MSc Level 7 · 2026

Secure Banking —
Authentication System

A critical online banking authentication system built with MFA, JWT sessions, RBAC, fraud detection, and account lockout — validated through DAST (Burp Suite), SAST (SonarQube), SCA (Snyk), and formal methods (Alloy). React, Node.js/Express, MongoDB, MVC architecture.

My Role
Software Engineer & Security
Context
MSc Level 7 · Staffordshire University · 2026
Stack
React · Node.js · MongoDB
Code
✦ Available on request
Scroll to explore
SecureBank Authentication System

What is SecureBank?

SecureBank is a full-stack online banking authentication system designed and built to address the real cybersecurity challenges facing modern digital banking — unauthorised access, brute-force attacks, credential stuffing, MFA bypass, session replay, and privilege escalation.

The system implements a defence-in-depth authentication model: users authenticate via password, complete multi-factor authentication via OTP, and receive a signed JWT session token. Every login attempt is logged and evaluated by a fraud detection service that analyses IP addresses, geolocation, and device metadata. Accounts lock automatically after three failed attempts. Role-based access control (RBAC) enforces strict separation between standard users and administrators.

The project goes beyond building the system — it validates it rigorously using four distinct security testing methodologies: dynamic testing with Burp Suite, static code analysis with SonarQube, dependency scanning with Snyk, and formal verification using Alloy — mapping every test against OWASP Top 10 categories and requirements from a full traceability matrix.

This was completed as part of my MSc at Staffordshire University in 2026, within the Critical Systems and Applications module at Level 7.

Quick Facts
Context
MSc Level 7 · Staffordshire University · 2026
Architecture
MVC · React · Node.js/Express · MongoDB
Security Testing
DAST · SAST · SCA · Formal Verification
OWASP Coverage
A01 · A03 · A07 mapped & tested

Why online banking authentication is critical.

Online banking authentication is one of the highest-value targets for attackers. A compromised account can lead to direct financial loss, identity theft, and regulatory penalties under GDPR and PCI DSS. Common attack vectors include brute-force credential guessing, phishing, session hijacking, MFA bypass, and privilege escalation to admin endpoints.

The core challenge is building a system that is simultaneously secure enough to resist real attack scenarios, usable enough that legitimate users can authenticate smoothly, and auditable enough that suspicious activity is logged and traceable for forensic investigation.

⚠️
Key Attack Vectors Addressed
Brute-force login attempts · NoSQL injection · MFA bypass via missing or misused tokens · RBAC privilege escalation to admin endpoints · Session replay using stale JWT tokens · Credential stuffing from distributed IPs · Sensitive data exposure in codebase
🛡️
Legal & Compliance Context
GDPR — lawful, transparent handling of user PII · PCI DSS — secure transmission and storage of authentication data · OWASP Top 10 — A01 (Broken Access Control), A03 (Injection), A07 (Auth Failures) · TLS/HTTPS for all communications · bcrypt password hashing · No plaintext secrets in logs or DB

MVC layered architecture with clear security boundaries.

The system follows a strict MVC architecture with three layers: a React-based presentation layer, a Node.js/Express controller and service layer, and a MongoDB database layer. All communication passes over HTTPS/TLS. The service layer holds all business logic — authentication, authorisation, fraud detection, and user management — keeping controllers lightweight and logic modular and testable.

System Architecture Diagram
Authentication system layered architecture — Presentation · Controller · Model · Database
👤
Guest
Access to public routes only — Home, Login, Register. No access to protected APIs or dashboards.
🏦
User
Banking customer who has authenticated with password and completed MFA. Access to protected customer dashboard.
🔧
Admin
Operational monitoring — can view all user login attempts, fraud events, and unlock locked accounts.

Defence in depth — layered security controls.

Each security control addresses a specific attack vector. Together they form a layered defence where compromising one layer does not mean compromising the system.

🔐
Multi-Factor Authentication (MFA)
After successful password verification, a one-time token is generated and delivered to the user via SendGrid. The OTP is stored hashed — never in plaintext. The full JWT session token is only issued after successful MFA verification.
🎟️
JWT Session Management
Signed JWT tokens carry the user ID and role. Tokens have short expiry. A temporary tempLoginToken is issued during MFA — it cannot be used to access protected endpoints. Logout invalidates the session token server-side.
🔒
Account Lockout
After 3 failed login attempts, the account is temporarily locked for 5 minutes (HTTP 423 response). The lockout counter is stored in MongoDB and resets after the lockout period expires. Protects against both manual and automated brute-force attacks.
🕵️
Fraud Detection
Every login attempt is logged with IP address, geolocation, device metadata, and user agent. The fraud service evaluates risk (LOW/HIGH) based on rules: multiple logins from different IPs, unusual geolocation changes, and repeated failures. High-risk events are stored in FraudEvent and visible to admins.
🛂
Role-Based Access Control (RBAC)
JWT payload carries the user role. Admin endpoints (/api/admin/*) are protected by middleware that validates role before executing controller logic. A regular user token attempting admin endpoints receives HTTP 403 Forbidden.
🧱
Input Validation (Zod)
All authentication endpoints validate input using Zod schema enforcement. Malformed inputs, unexpected data types, and injection payloads are rejected with a 400 Validation Error before reaching the database layer. Prevents NoSQL injection at the input boundary.

Four-method security validation approach.

The system was validated using a comprehensive four-layer security testing strategy — each method targeting a different class of vulnerability and providing complementary evidence of security. Every finding was mapped to an OWASP Top 10 category and a requirements traceability matrix entry.

Method Tool What it tested Result
DAST Burp Suite NoSQL injection, brute-force lockout, MFA bypass, RBAC bypass, session replay — live against running app All 5 attack scenarios mitigated. No exploitable vulnerabilities found in core auth logic.
SAST SonarQube Static code analysis — hardcoded secrets, injection risk, insecure patterns across 4.3k lines 7 issues found. 3 true positives mitigated. 2 false positives justified. Quality Gate: Passed.
SCA Snyk Dependency vulnerability scanning — third-party packages for known CVEs 1 medium (CSRF — false positive, JWT auth model not susceptible). 1 low resolved.
Formal Methods Alloy Formal verification of authentication safety rules and fraud detection logic 3 assertions verified: NoSessionWithoutSuccessfulLogin, MFA enforcement, multi-IP fraud flagging.

Five attack scenarios tested with Burp Suite.

Each DAST test case simulated a real attack scenario using Burp Suite Repeater against the live running application. All five attacks were successfully mitigated by server-side controls.

MITIGATED
NoSQL Injection — OWASP A03
Injected {"$ne": null} into the email field of POST /api/auth/login. Server returned HTTP 400 "Validation error: Invalid input: expected string, received object" — Zod schema enforcement rejected the payload before it reached MongoDB.
MITIGATED
Brute-Force Login & Account Lockout — OWASP A07
Submitted incorrect password 3 times in Burp Repeater. First attempts returned HTTP 401 "Invalid credentials". After the 3rd failure, account triggered HTTP 423 "Account temporarily locked. Try again later." — even correct credentials were rejected while locked.
MITIGATED
MFA Bypass — OWASP A07
Two scenarios: (A) accessing GET /api/user/me with no Authorization header → HTTP 401 "Authentication required". (B) using tempLoginToken from the login step as an access token on a protected endpoint → HTTP 401 "MFA required". The system correctly distinguishes temporary MFA tokens from fully authenticated session tokens.
MITIGATED
RBAC Bypass — OWASP A01
Used a valid user-role JWT to call GET /api/admin/fraud-events (an admin-only endpoint). Server returned HTTP 403 "Forbidden" — role middleware correctly blocked access without exposing admin data or crashing.
MITIGATED
Session Replay / Token Reuse — OWASP A07
Captured a valid JWT in Burp, logged out from the application, then replayed the captured token against GET /api/user/me. Server returned HTTP 401 "Session expired" — logout correctly invalidated the token server-side.
Brute-Force Lockout Test
Burp Repeater — 401 → 423 lockout transition after 3 failed attempts
RBAC Bypass Attempt
Burp Repeater — user token rejected on admin endpoint with 403

SonarQube & Snyk — code and dependency analysis.

Static analysis with SonarQube identified 7 security issues across 4.3k lines of code. Each was analysed, classified as true positive or false positive, and either remediated or formally justified. After remediation, the main branch Quality Gate status reads Passed with 0 open security issues.

SonarQube Quality Gate Passed
SonarQube post-remediation — Quality Gate Passed, 0 open security issues
Key SAST findings & outcomes
✓ MitigatedHardcoded MongoDB credentials in .env — rotated, removed from version control, excluded via .gitignore
✓ MitigatedHardcoded SendGrid API key — revoked, replaced, secured in environment variables
✓ MitigatedNoSQL injection risk in adminController.js — explicit input validation added
⊘ False positiveNoSQL injection flagged in mfaRoutes.js and authRoutes.js — these are routing files only; all DB access is in service layers with Zod-validated inputs

Alloy model — proving security properties formally.

Three security assertions were verified using the Alloy formal modelling tool — proving that the system's authentication and fraud detection rules hold under all possible system states within the model's scope. Alloy verification provides mathematical confidence that the design-level security properties are correct, independent of the implementation.

NoSessionWithoutSuccessfulLogin
PASS
A session cannot exist unless the user has successfully completed both password and MFA verification. Initial run produced a counterexample — the model was missing a constraint. Adding a SessionsRequireSuccessfulLogin fact resolved it. Re-run: no counterexample found.
MultiIPFailuresImpliesFlag
PASS
If a user performs multiple failed login attempts from different IP addresses in adjacent time steps, a FraudFlag must exist. Models detection of distributed brute-force and credential-stuffing attacks. Counterexample found on first run → fraud detection fact added → PASS.
NoSessionWithoutMFA
PASS
A session cannot exist unless MFA has been successfully completed — even if password verification succeeded. Directly validates that MFA bypass is impossible in the formal model. No counterexample found on first run.

Built and tested with industry tools.

⚛️
React
🟢
Node.js / Express
🍃
MongoDB
🎟️
JWT
🔐
bcrypt
Zod Validation
🔍
Burp Suite
📊
SonarQube
🛡️
Snyk
⚙️
Alloy
📧
SendGrid
🌍
IPinfo (Geo)

What was built and validated.

5/5 DAST attack scenarios mitigated NoSQL injection · Brute-force · MFA bypass · RBAC · Session replay
Passed SonarQube Quality Gate 0 open security issues post-remediation
3/3 Alloy assertions verified Auth safety · MFA enforcement · Fraud detection

What I learned.

01
Security testing requires a layered approach. No single testing method finds everything. DAST catches runtime behaviour, SAST catches code patterns, SCA catches dependency risks, and formal verification catches design-level flaws. Each layer found things the others would have missed.
02
False positives require evidence, not dismissal. Two SAST findings initially flagged as NoSQL injection in route files were classified as false positives — but only after a manual review documenting exactly why they weren't exploitable. In a security context, "it's fine" isn't enough; the justification must be traceable.
03
Formal verification reveals incomplete thinking. Both the authentication safety assertion and the fraud detection assertion found counterexamples on first run — not because the implementation was wrong, but because the formal model hadn't yet encoded all the constraints. Alloy forces precision that informal testing doesn't.
Next Project →
Breast Cancer Prediction — ML Web App
View Case Study →
← Back to Portfolio
Share: in