The Bank API is a design reference project suitable to bootstrap development for a compliant and modern API.
The API complies to:
β OWASP API Security Top 10 - v2023 via Spectral OWASP API Security ruleset
β OpenAPI Specification v3.1.1 via Spectral "oas" ruleset
β Dutch Public Sector (NLGov) REST API Design Rules via API Design Rules ruleset
β Additional naming conventions, structure, and clarity via Bank API project ruleset
β California Consumer Privacy Act (CCPA) and General Data Protection Regulation (GDPR) via ASP.Net Core Compliance
β
RFC 7515 - JSON Web Signature (JWS) for response signing, via X-JWS-Signature
header
β
RFC 7517 - JSON Web Key Set (JWKs) for validating JWS responses, via /.well-known/jwks.json
endpoint
-
ASP.NET Core 10.0 - Minimal API for API development, with following base services:
-
Resilience for resilience when calling downstream APIs
-
Compliance for redacting sensitive data
-
Health checks for checking health status
-
Service Discovery for resolving endpoints from config
-
Hybrid Cache for caching
-
Rate limiting for rate limiting
-
API Key, JWT bearer and OpenID Connection-based authentication for security, with:
- token reuse prevention for Entra ID tokens
-
OpenApi for generating OpenAPI specifications
-
Cross-Origin Resource Sharing (CORS) for cross-origin requests
-
Validation for validating requests on endpoints
-
-
OpenTelemetry (OTel) for observability
-
.NET Aspire for development bootstrapping and client integrations
-
Kiota API client generation for calling downstream APIs
-
Gridify for filtering, ordering and paging
-
Scalar for interactive API documentation
-
Spectral for linting
-
TUnit for unit tests
-
REST Client extension in Visual Studio Code for quick local tests via
.http
files
Technically, the design is layered like the following flowchart.
flowchart TB
apis[BankApi.Service.Beta / BankApi.Service.Stable]
aspire[BankApi.Orchestration]
test[BankApi.Tests]
infra_gen[Infra.Generated]
specs_gen[Specs.Generated]
subgraph core[BankApi.Core]
Defaults
DownstreamClients
Implementation
end
Defaults --> Implementation
DownstreamClients --> Defaults
DownstreamClients --> Implementation
Defaults --> apis
Implementation --> apis
Implementation --> test
apis --> aspire
apis --> specs_gen
aspire--> infra_gen
If not using the Dev Container, install:
-
Use a
pwsh
shell (for a click-a-long experience). -
(Optionally) regenerate the GitHub downstream API client by going to the Kiota workspace and clicking
Re-generate
underclients
. -
(Optionally) regenerate the ASP.NET Core HTTPS development certificate:
dotnet dev-certs https --clean && dotnet dev-certs https -ep ./.certs/AspNetDev.pfx -p '' --trust
-
(Optionally) regenerate the Aspire manifest:
dotnet run --project BankApi.Orchestration --publisher manifest --output-path ../Infra.Generated/aspire-manifest.json
-
Generate a new JWT-token for secured endpoints:
dotnet user-jwts create --scope "bank_api" --role "banker" --valid-for 3650d --project BankApi.Service.Stable
-
Run
dotnet build
to output the OpenAPI definition -
Validate the OpenAPI definition by going to the openapi_v1.json definition and check for problems via the Spectral extension.
This mode just runs the ASP.NET Core API.
-
Make sure the docker runtime is started.
-
Start the standalone Aspire Dashboard for developer visualization:
docker run --rm -it ` -p 18888:18888 ` -p 4317:18889 ` --name aspire-dashboard ` mcr.microsoft.com/dotnet/aspire-dashboard:latest
Copy the url shown in the resulting output when running the container (e.g. http://localhost:18888/login?t=123456780abcdef123456780) and open that in a browser, or paste the key part seen after
/login?t=
when the login dialog is shown. The token will change each time the container is started. -
Run the launch config
API - Stable release channel
.
This mode starts the Stable and Beta versions of the API in context of .NET Aspire.
-
Make sure the docker runtime is started.
-
Run the launch config
Aspire Orchestration
.
-
To extend OpenTelemetry logging to Application Insights, expand the OpenTelemetry exporter.
-
The compliance NullRedactor doesn't seem to work, the redactor is already defined at Builder.Compliance.cs but not used because of the issue.
-
Dependabot is enabled for
nuget
packages but wildcard version notation isn't supported yet, which is used extensively in this project. -
The OpenAPI document generator shipped with .NET 10 does not fully support API versioning, a simpler approach with PathBase is used for now, which is also more convenient for Azure API Management usage.
-
Extending Spectral rulesets from an NPM package can be problematic.
-
Generic exception handling is minimally implemented via ErrorHandling.cs.
-
API owners usually have customers outside of their own company - or outside of their own domain within a company - which inherently means adoption time will be slower for API contract changes, this is why there is a
Stable
andBeta
version of the API in this project, inspired by the Microsoft Graph API Current/Beta versioning design. New or modified contract-breaking (beta) operations to API consumers may be served via theBeta
version without distracting users on theStable
version.Do not confuse this versioning scheme as a replacement for DTAP; it is merely complementary to it. Many API changes will affect both the
Stable
andBeta
endpoints (such as changes to the underlying shared database). That's why they both share a common layer in the form ofBankApi.Core
.Nonetheless, versioning is very opinionated and one should always see what the best business and technical fit is. This might change over time and from project to project.
-
Dev Containers with the
docker-outside-of-docker
feature instead ofdocker-in-docker
do not work, for now we're usingdocker-in-docker
.
Please see the Reddit r/dotnet post 1 and post 2 about this project for more considerations and information.
-
If debugging isn't working properly, please clear the Extension Host Cache at
%AppData%\Code\CachedData
(on Windows) and restart VSCode. -
If getting the error
unable to get local issuer certificate
with Spectral, make sure to add the CA of the proxy toNODE_EXTRA_CA_CERTS
and restart VSCode, for example:
[Environment]::SetEnvironmentVariable('NODE_EXTRA_CA_CERTS', 'C:\ZscalerRootCA.crt', 'User')
- Extending Rulesets with local filepath not refreshing when working on Spectral rulesets in VSCode. Force an update in the .spectral/main.yml when changing a file that is used as an extend.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.