A full-stack sample application demonstrating how Ember.js and ASP.NET Core work together seamlessly using OpenIddict for authentication and token refresh, and JsonApiDotNetCore for full JSON:API specification compliance.
Back in 2017, Jared Nance created an excellent video series building the initial version of this demo:
- Part 1: Server Setup
- Part 2: Client Setup
- Part 3: Server Authentication and Authorization
- Part 4: Client Sessions
- Part 5: Persisting Data
This repository has since been updated to modern .NET 10, Ember.js 6.12 LTS (built with Embroider + Vite), Ember Data 5.3 LTS, and OpenIddict 7.
Before getting started, make sure you have the following installed:
- .NET 10 SDK (
dotnet --versionshould return10.0.x) - Node.js (
>= 20.19.0, LTS recommended) and npm - Docker (or an existing PostgreSQL instance)
- Google Chrome (required by Testem for running Ember acceptance tests)
- Optional: Visual Studio Code (with the C# Dev Kit extension), Visual Studio 2026, or JetBrains Rider.
When the API runs for the first time, it automatically creates the PostgreSQL database and seeds two demo user accounts:
| Username | Password | Initial Seeded Item | |
|---|---|---|---|
guest |
Guest1! |
guest@email.com |
"owned-by-guest" |
john |
P@ssw0rd! |
john@email.com |
"owned-by-john" |
User Data Isolation: The API enforces user tenancy through TodoItemDefinition. When logging in as guest, you will only see and manage todo-items owned by guest. When logging in as john, you will only see and manage items owned by john.
The application expects a PostgreSQL instance with the connection details defined in TodoListAPI/appsettings.json. You can start it using Docker Compose:
docker compose up --detach --wait- This starts a PostgreSQL database container and a pgAdmin container (accessible at http://localhost:5050, preconfigured to automatically connect to the database).
- To stop the containers:
docker compose down
- To stop the containers and remove persistent data (reset the database):
docker compose down --volumes
Note
The API will automatically create database tables and seed the demo users and todo-items on its first run.
cd TodoListAPI
dotnet run- The API reads development settings from
Properties/launchSettings.jsonand starts listening on:http://localhost:5000/https://localhost:44344/
- You can test API endpoints directly in your editor using the preconfigured TodoListAPI.http file.
In a separate terminal window:
cd TodoListClient
npm install
npm start- Open http://localhost:4200/ in your browser.
- Sign in using either the
guestorjohncredentials listed above.
The API uses OpenIddict configured with OAuth2 password grant and refresh token flows (connect/token). By default, tokens have long lifetimes in development.
To observe token expiration and automatic background token refresh in action:
- Open
TodoListAPI/Program.csand uncomment these two lines:options.SetAccessTokenLifetime(TimeSpan.FromSeconds(15)); options.SetRefreshTokenLifetime(TimeSpan.FromSeconds(30));
- Restart the API (
dotnet run). - In your browser, log in to the Ember app (http://localhost:4200) and open Developer Tools (F12 → Network tab).
- Filter network traffic by
token. - Wait ~15 seconds: Ember Simple Auth automatically detects that the access token is expiring and transparently sends a
POST /connect/tokenrequest withgrant_type=refresh_tokento retrieve a fresh token. The user session stays active without interruption or forced re-login.
Alternatively, you can test the refresh token flow without the UI using TodoListAPI/TodoListAPI.http.
From the TodoListClient directory:
- Run all linters and tests:
npm test - Run Ember acceptance tests headlessly:
npm run test:ember
- Run Ember tests interactively (in-browser with live reload):
Start the dev server (
npm start) and navigate to http://localhost:4200/tests. - Run code linters (ESLint, Prettier, Stylelint, Template-Lint):
npm run lint
- Automatically fix lint and formatting issues:
npm run lint:fix
- Build production assets:
npm run build
The repository includes an end-to-end test suite built with Playwright that validates the entire stack against the real PostgreSQL database, ASP.NET Core API server, and Ember.js client app.
-
Start the database in Docker:
docker compose up --detach --wait
-
From the
TodoListClientdirectory, install browsers (one-time setup):cd TodoListClient npx playwright install chromium -
Run the tests:
npm run test:e2e
Tip
Automatic Server Management: If the backend API (dotnet run) and frontend client (npm start) are already running, Playwright reuses them automatically. If they are not running, Playwright launches them in the background, runs the test suite, and shuts them down upon completion.
You can also run tests interactively with the Playwright UI runner:
npx playwright test --uiThe client project uses standard npm packaging and is configured with Ember's modern Vite blueprint (@ember/app-blueprint). To upgrade Ember dependencies in the future, use npx ember-cli-update:
- Run the update tool:
npx ember-cli-update
- Review and resolve any merge conflicts in project configuration files.
- Run applicable codemods:
npx ember-cli-update --run-codemods
- Reinstall dependencies:
npm install
- Run tests to confirm everything still passes:
npm test