Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ApiKeyManager

A production-inspired REST API built with ASP.NET Core that demonstrates how real SaaS platforms (Stripe, OpenAI) protect their APIs with key-based authentication, rate limiting, and usage analytics.

Tech Stack

.NET SQL Server Redis

  • ASP.NET Core 10 — REST API, custom middleware pipeline
  • Clean Architecture — Domain, Application, Infrastructure, API
  • Entity Framework Core + SQL Server — persistence, EF Fluent API
  • Redis — cache-aside key validation, sliding window rate limiting
  • ASP.NET Core Identity + JWT — user authentication
  • Channel<T> + BackgroundService — non-blocking usage logging

Architecture

Domain → Application → Infrastructure → API

Four layers, strict dependency rules. Business logic never touches the database. Every business rule is testable without spinning up a database or Redis.

Project Structure

ApiKeyManagement/
├── API/             # Controllers, Middlewares, Program.cs
├── Application/     # CQRS, Interfaces, DTOs
├── Domain/          # Entities, Exceptions
└── Infrastructure/  # EF Core DbContext, Redis Services, Identity

Getting Started

Prerequisites

Setup Instructions

  1. Clone the repository

    git clone https://github.com/Haitham-AbdelKarim/ApiKeyManagement.git
    cd ApiKeyManagement
  2. Configuration Update the appsettings.json file in the API project with your connection strings for SQL Server and Redis, as well as your JWT configuration.

  3. Database Migrations Navigate to the API folder and run the EF Core migrations to create the database schema:

    cd API
    dotnet ef database update
  4. Run the Application

    dotnet run

    The API will start. Navigate to https://localhost:{port}/swagger (or the port specified in launchSettings.json) to explore the interactive API documentation.

How it works

Two completely separate authentication flows:

JWT (Bearer token)     →  manage your account
                          POST /api/auth/register
                          POST /api/auth/login
                          POST /api/keys
                          GET  /api/keys
                          DELETE /api/keys/{id}
                          GET  /api/usage/summary
                          GET  /api/usage/history

API Key (X-Api-Key)    →  call protected endpoints
                          GET  /api/v1/status
                          POST /api/v1/text/analyze

Every request to /api/v1/ passes through three middleware classes before reaching any controller:

ApiKeyExtractionMiddleware  →  reads header, SHA-256 hashes it
ApiKeyValidationMiddleware  →  Redis cache-aside → SQL fallback
RateLimitingMiddleware      →  atomic sliding window via Lua script
UsageLoggingMiddleware      →  logs after response (non-blocking)

API Usage Example

  1. Get a JWT Token:

    curl -X POST https://localhost:7001/api/auth/login \
      -H "Content-Type: application/json" \
      -d '{"email":"user@example.com", "password":"Password123!"}'
  2. Generate an API Key:

    curl -X POST https://localhost:7001/api/keys \
      -H "Authorization: Bearer <YOUR_JWT_TOKEN>" \
      -H "Content-Type: application/json" \
      -d '{"name": "Production Key"}'
  3. Call a Protected Endpoint:

    curl -X GET https://localhost:7001/api/v1/status \
      -H "X-Api-Key: <YOUR_RAW_API_KEY>"

Key Decisions

API keys are never stored — only their SHA-256 hash. The raw key is returned once on creation and discarded. A database breach exposes only hashes.

Redis cache-aside — validated keys are cached for 5 minutes. Cache hits bypass SQL Server entirely. Revocation immediately invalidates the cache entry.

Lua script for rate limiting — runs atomically inside Redis. Prevents the race condition that makes C# locks and Redis transactions ineffective across multiple servers.

Non-blocking usage loggingChannel<UsageRecord> decouples the middleware (producer) from the background worker (consumer). The caller never waits for a DB write.

Rate Limit Plans

Plan Requests/min Requests/month Max Keys
Free 10 1,000 3
Pro 60 50,000 10
Enterprise 300 500,000 50

Rate limit headers are attached to every response:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1746529260

Planned Enhancements

  • Hangfire scheduled jobs (monthly reset, quota alerts)
  • Unit and integration tests (xUnit)
  • Email notifications at 80% quota
  • IP allowlisting per key
  • Azure deployment

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages