E-commerce Inventory API with JWT Auth
Build a secure inventory API for an online store with ASP.NET Core. It manages products, categories and stock movements (goods received, items sold, adjustments), and knows exactly how many units of each product are in stock. Users log in and receive a JWT token. Viewers can read data, while only admins can change products or record stock movements. A low-stock endpoint lists products that need reordering. You'll learn how JWT authentication works, role-based authorization policies, Entity Framework Core with migrations, keeping stock consistent with transactions and concurrency checks, and writing integration tests that prove your security rules work.
- Estimate
- ~14.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
ASP.NET Core · Entity Framework Core · JWT Bearer
Project roadmap
- 01
Set up the API and data model
~2hCreate an ASP.NET Core Web API (.NET 8 or newer) with Entity Framework Core and a database provider (PostgreSQL or SQLite). Define Category, Product (name, SKU unique, price, reorder threshold, current stock) and StockMovement (product, quantity change, reason, user, time) entities. Create the initial migration and seed a few categories and products. Done when: dotnet ef database update creates the schema with seed data.
- 02
Register users and issue JWTs
~2.5hAdd a User entity with a unique email, a password hash (use PasswordHasher<T> from ASP.NET Core Identity) and a role (Admin or Viewer). Add POST /auth/register (creates viewers only) and POST /auth/login, which returns a signed JWT with the user id and role claims and a 60-minute expiry. Keep the signing key in configuration or user secrets, never in code. Done when: logging in returns a token whose claims decode correctly, for example on jwt.io.
- 03
Protect the endpoints with roles
~2hConfigure JWT bearer authentication (issuer, audience, signing key and lifetime validation). Define two authorization policies, CanRead (Admin or Viewer) and CanWrite (Admin only), and apply them with [Authorize(Policy = ...)]. Seed one admin account from configuration. Done when: a request without a token gets 401, a viewer calling a write endpoint gets 403, and an admin succeeds.
- 04
Manage products and categories
~2hImplement GET /products (with category filter and pagination), GET /products/{id}, POST, PUT and DELETE /products, and the same for categories. Validate input with data annotations (required name, price above 0, a non-negative threshold) and return ProblemDetails for errors. Deleting a category that still has products returns 409. Done when: all endpoints work for admins and return correct validation errors.
- 05
Record stock movements
~2.5hAdd POST /products/{id}/stock-movements with a quantity change and a reason (Received, Sold, Adjustment). In one transaction, insert the movement and update the product's stock, rejecting any movement that would make stock negative. Add a concurrency token (a RowVersion column) to Product so two simultaneous movements can't produce a wrong total; retry once on a conflict. Add GET /products/{id}/stock-movements. Done when: stock always equals the sum of its movements.
- 06
List low-stock products
~1hAdd GET /inventory/low-stock, returning products whose stock is at or below their reorder threshold, sorted by how far below they are, with the quantity needed to get back above it. Allow a ?category= filter. Done when: after recording sales, the products that drop below their threshold appear in the list.
- 07
Write integration tests
~2.5hUsing WebApplicationFactory and xUnit with a test database, test that: anonymous requests get 401, viewers can read but get 403 on every write endpoint, admins can write, stock can't go negative, and the low-stock list is correct. Create tokens for the tests by calling the login endpoint. Done when: dotnet test passes.
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack