Skip to content
Personal / Career Engineering journal● Public portfolio
← All entriesProject dashboard ↗GitHub ↗

AWS / CLOUD · SEPTEMBER 26, 2026

Building a Secure Serverless IT Help Desk on AWS

Closing Family IT Help Desk v0.2 with authenticated administration, backend-enforced security controls and a ticket lifecycle validated from submission through resolution.

I am already the unofficial IT department for family and friends. Family IT Help Desk started as a way to turn those scattered support requests into a useful AWS project. By v0.2, it had become a working serverless application with authenticated users, persistent tickets, email notifications, administrative controls and a complete ticket lifecycle.

This entry is the completion record for v0.2. The earlier journal entry documents how the project started and reached its first working version. I wanted to keep that history intact rather than rewrite the original article every time the application grew.

The completed architecture

AWS Lambda provides the backend application logic. API Gateway exposes the protected API. Amazon Cognito handles registration, email verification, authentication and authorization. DynamoDB stores the authoritative ticket records, Amazon SNS provides ticket notifications, and CloudWatch provides the logging and operational visibility needed to troubleshoot the system.

The browser is only one layer of the application. A successful-looking screen is not treated as proof that a ticket exists or that a state transition succeeded. The backend and persisted ticket record remain authoritative.

Security belongs on the backend

Security was part of the design rather than a final checklist. Users can register and verify their email through Cognito, but that alone does not grant access. Membership in ApprovedUsers provides an additional approval gate for the Help Desk. Administrative functionality is separated behind a HelpDeskAdmins authorization boundary.

The protected API uses JWT-based authentication. The browser uses the OAuth authorization-code flow with PKCE and does not contain a client secret. CORS is restricted to the intended frontend origin, while Lambda performs backend authorization and validation instead of trusting what the browser chooses to display.

Ticket priority is also controlled by the backend. A client cannot simply declare its own priority. Security-related submissions follow a deterministic escalation path to Critical priority and present a security warning to the user.

Server-side validation covers required fields, accepted categories and impact values, and request-size limits. During validation I deliberately sent malformed and incomplete requests, invalid category and impact values, and oversized requests to confirm that the API rejected them instead of relying on frontend validation.

Closing the ticket lifecycle

v0.2 added authenticated ticket management and completed the workflow from Submitted → In Progress → Resolved. Administrators can retrieve tickets and update their status through protected application paths, while the user-facing interface reflects the resulting state.

The lifecycle was tested end to end rather than as isolated UI actions. A ticket could be submitted, persisted, retrieved, moved into progress, resolved and restored later with the correct authoritative state. A fresh-ticket smoke test was also completed after the temporary debugging instrumentation had been removed.

When the database and browser disagreed

One of the most useful bugs appeared when DynamoDB correctly showed a ticket as In Progress while the browser still displayed Submitted. That made the distinction between backend truth and presentation state impossible to ignore.

Tracing the restore path showed that the application was obtaining the correct state, but later frontend initialization could overwrite the restored workflow stages. The fix was to establish the default UI state first and restore the authoritative ticket state afterward.

A separate presentation problem came from JavaScript expecting a result-status element that was missing from the HTML. Neither problem required weakening the backend controls. They required following the data across storage, API behavior, application logic and DOM rendering until the layer causing the mismatch was identified.

Testing more than the happy path

The final acceptance work covered the normal lifecycle as well as negative paths: backend field validation, invalid category and impact rejection, oversized-request rejection, security-ticket Critical escalation, persistence, notification behavior, authoritative state restoration and a clean regression smoke test.

That distinction matters to me. “The form submitted once” is not the same acceptance criterion as “the application enforces its rules and restores the correct state after the user leaves and returns.”

Freezing v0.2

Family IT Help Desk v0.2 is now the completed baseline. I am deliberately freezing it instead of immediately adding another feature. The core application works without AI, and that is an architectural requirement rather than a temporary limitation.

A possible v0.3 may add a tightly bounded Amazon Bedrock troubleshooting assistant. If that happens, AI will remain optional, usage will need to be controlled, and security-sensitive or high-priority cases will bypass it. The assistant should enhance a working help desk, not become a dependency for basic support.

What this project taught me

The project began as a Lambda exercise, but the useful learning spread much further: serverless architecture, authentication and authorization, API security, OAuth and PKCE, JWTs, persistence, notifications, input validation, security boundaries, state restoration, negative-path testing and debugging across multiple application layers.

Most importantly, it reinforced a habit I want to keep across the rest of my cloud work: define what “complete” means, validate the system against that boundary, document what failed, and stop adding features long enough to preserve a known-good baseline.

Family IT Help Desk is part of my broader Cloud Engineering Portfolio, where I am documenting the architecture, decisions, testing and troubleshooting behind my hands-on cloud work.

Family IT Help Desk project documentation ↗

Explore the Cloud Engineering Portfolio ↗

← Back to the engineering journal