SignaCore is a .NET 10 identity and authentication service. It centralizes account authentication, issues RS256 JWTs, rotates refresh tokens, exposes JWKS discovery, and provides an administrative Vue console.
- Password, SMS, WeChat, LDAP, and refresh-token grants
- Per-application admission policies for SMS, LDAP, and WeChat, with self-service WeChat binding
- RFC 6749 token endpoint and RFC 7009 revocation at /oauth2/, alongside the legacy /api/auth/ contract
- Per-application access-token audience isolation
- RS256 signing-key generation, encrypted private-key storage, rotation, and JWKS publication
- Application registration, callback claim enrichment, and gateway authentication
- User/profile administration, audit trails, login history, lockout, and cleanup jobs
- PostgreSQL and SQLite through EF Core provider-specific migrations
- Database-backed global configuration with web-based first-run setup
- Optional Consul service discovery
- OpenTelemetry, Prometheus, sanitized structured logging through the ServiceMantle Serilog pipeline, and optional Loki export over
httporhttps(the scheme is a deployment decision), with an explicit no-authentication opt-in
| Path | Purpose |
|---|---|
src/SignaCore.Database |
EF Core model, repositories, and PostgreSQL migrations |
src/SignaCore.Database.Migrations.* |
SQLite migration assembly |
src/SignaCore.Domain |
Authentication, token, key, SMS, LDAP, and audit logic |
src/SignaCore.Host |
ASP.NET Core host, HTTP API, SPA hosting, and Dockerfile |
src/SignaCore.Admin |
Vue 3 administrative console |
samples |
Integration samples: the confidential Reference BFF (preferred for high-privilege clients) and the zero-dependency Public SPA |
tests |
Unit and integration/contract test projects |
docs |
Architecture, operations, schema, and feature documentation |
.github |
GitHub Actions, dependency automation, and contribution templates |
Requirements: .NET SDK 10, Node.js 22.12+, 24+, or 26+ with npm for the admin UI, and Docker for the container smoke test.
SignaCore pins all eight ServiceMantle packages to the official 0.3.3 release: the core package, Web,
Discovery, Logging, Diagnostics, Persistence.Relational, and the PostgreSQL/SQLite
providers. Upgrade or roll back the complete binaries together; do not mix the retired adapter
assemblies with capability-named assemblies. This package migration adds no database migration:
HTTP routes, configuration keys, JWT/JWKS, management Cookie/Data Protection purposes, and
existing migration history remain unchanged. A binary rollback does not undo an independently
applied irreversible database migration (see migration guidance).
The host references the ServiceMantle.Web NuGet package for the shared request-correlation
middleware; its version is pinned centrally in Directory.Packages.props and restores from
nuget.org like every other dependency — a clean checkout needs no source checkout, submodule, or
extra feed configuration.
dotnet restore SignaCore.slnx
dotnet build SignaCore.slnx --configuration Release
dotnet test tests/SignaCore.Tests/SignaCore.Tests.csproj
dotnet test tests/SignaCore.IntegrationTests/SignaCore.IntegrationTests.csproj
npm --prefix src/SignaCore.Admin ci
npm --prefix src/SignaCore.Admin run test:coverage
npm --prefix src/SignaCore.Admin run buildCopy src/SignaCore.Host/appsettings.Development.example.json to
src/SignaCore.Host/appsettings.Development.json, point it at a local PostgreSQL instance (or
override Database__ConnectionString), then run:
dotnet run --project src/SignaCore.Host/SignaCore.Host.csprojThe first run against an empty database enters Setup Mode. Open /setup, enter the one-time setup
code printed to the console, and supply the public base URL and administrator credentials. See
first-run setup.
The API listens on port 5002 by default; override it with the Endpoints__Http environment variable (or another Endpoints:Http configuration source). Useful endpoints include /health/live, /health/ready, /.well-known/openid-configuration, /.well-known/jwks (also reachable as /.well-known/jwks.json), /metrics (requires registered application credentials), /oauth2/token, /api/auth/token, and /admin.
IMAGE_TAG=latest ./build.sh
mkdir -p config
chmod 700 config
./start.shOn first start, open /bootstrap and enter the one-time code printed by docker logs signacore.
The protected UI tests the database, generates the root key for a new install, and atomically creates
config/signacore.bootstrap.json. The directory is mounted read-write so later authenticated edits
can replace the file. Everything else is configured through first-run setup and administration
pages. A brand-new installation stays live but not ready during both configuration phases, and the
launcher reports that instead of rolling back.
Global application configuration lives in the business database, in the shared service_settings
aggregate. Every instance
reads the same active configuration, changes are transactional and audited, and there is no
per-instance drift. See Shared settings and the
legacy table retirement.
Only what is required to open and decrypt that database stays outside it, in one writable bootstrap
file at /app/config/signacore.bootstrap.json: the database provider, server version, and connection
string, plus the inline external root key. The whole file is a mode-0600 secret on persistent
storage and must be backed up with the database.
Plain-HTTP deployments are a deployment decision
(ADR 0008): http and https
redirect URIs, public base URLs, and issuers are accepted equally in every environment, and the
former private-network HTTP testing allowlist (security.hosted_login_http_test_origins) and its
Testing environment gate are retired. See plain-HTTP deployments;
terminate TLS in front of the service for public deployments.
The external configuration stays minimal — the bootstrap file, the first-install facts, and the listening port; per-instance environment variables only override managed values, and a deployment still supplying managed keys externally gets warnings instead of startup failures (ADR 0009).
Important defaults, all stored in the database and editable after installation:
| Setting | Default |
|---|---|
Endpoints:PublicBaseUrl |
collected by first-run setup |
Jwt:Issuer |
the normalized public base URL |
Jwt:Audience |
SignaCore.Services |
Consul:Discovery:Enabled |
false |
app.title |
SignaCore (the launcher APP_TITLE labels only the bootstrap and setup pages) |
See configuration for the full catalog.
The rename changes .NET namespaces and assembly names from the former product name to SignaCore.*. It also changes the default image/container, database name, Consul service/prefix, JWT issuer/audience, telemetry source, and UI package name. Existing deployments should override old JWT values during a rolling migration if previously issued tokens must remain valid, point the bootstrap connection string at the existing database if data must be retained, and reuse the previous RSA_MASTER_KEY value as the bootstrap root key so stored signing keys remain decryptable. Database table names and HTTP contracts were not renamed.
Start with the documentation index, system design, configuration, and deployment. Contributions should follow CONTRIBUTING.md, and vulnerabilities should be reported through SECURITY.md.