SaveApis.Framework

Documentation for SaveApis.Framework

View on GitHub

ZitadelInstaller — Web

Key: Zitadel
Default Enabled:
Package: SaveApis.Framework.Web


Purpose

Integrates Zitadel as the authentication provider via token introspection (not JWT validation). The installer uses a service account JWT profile to authenticate itself against the Zitadel introspection endpoint and caches token results for 5 minutes.

Note: If Zitadel:JwtProfile is empty or missing, the installer silently skips registration — no error is thrown. This makes it safe to run without Zitadel in local development while keeping the installer enabled.


What It Does

Builder phase (only when JwtProfile is non-empty):

Application phase: none — middleware is provided by AuthenticationInstaller.


Dependencies

Dependency Direction Requirement Description
AuthenticationInstaller After Required Base auth services must be registered first
AuthorizationInstaller After Required Authorization must be registered before Zitadel
ControllerInstaller Before Optional  
OpenApiInstaller Before Optional Adds OAuth2 security scheme to the OpenAPI doc
ScalarInstaller Before Optional Pre-selects Zitadel security scheme in Scalar

Configuration

appsettings.json

{
  "Zitadel": {
    "Authority": "https://auth.example.com/",
    "JwtProfile": "{\"type\":\"serviceaccount\",\"keyId\":\"...\",\"key\":\"-----BEGIN RSA PRIVATE KEY-----\\n...\\n-----END RSA PRIVATE KEY-----\\n\",\"appId\":\"...\",\"clientId\":\"...\"}",
    "Scopes": {
      "openid": "OpenID Connect",
      "profile": "Profile",
      "email": "Email",
      "urn:zitadel:iam:user:resourceowner": "Organization Name"
    }
  }
}

Environment Variables

Variable Type Required Description
Zitadel__Authority Uri Yes Zitadel instance base URL (trailing slash required)
Zitadel__JwtProfile string Yes Full JSON content of the Zitadel service account key file
Zitadel__Scopes__openid string No Scope label shown in Scalar/OpenAPI
Zitadel__Scopes__profile string No Scope label
Zitadel__Scopes__email string No Scope label
Zitadel__Scopes__urn:zitadel:iam:user:resourceowner string No Scope label

Example:

Zitadel__Authority=https://auth.example.com/
Zitadel__JwtProfile={"type":"serviceaccount","keyId":"123","key":"-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n","appId":"456","clientId":"789"}

Tip: In production, set Zitadel__JwtProfile from a secret manager (e.g. Kubernetes secret, Azure Key Vault). Never commit the JWT profile JSON to source control.


Default Scopes

When Scopes is not configured, the following defaults are used (visible in the Scalar UI and OpenAPI document):

Scope Label
openid OpenID Connect
profile Profile
email Email
urn:zitadel:iam:user:resourceowner Organization Name

InstallerContext Extension

installer.WithZitadel(bool enabled = true);

Example — disable in development:

installer.WithZitadel(false);

When Zitadel is disabled, OpenApiInstaller and ScalarInstaller automatically omit the Zitadel OAuth2 security scheme from their output. This is detected via context.Enabled(ZitadelInstaller.Key).