Skip to content
bitzorcas
中EN

Reference

Pre-Seeded Demo Accounts and the Password Injection Contract: Zero-Trust Seeding and Multi-Tenant Isolation

A deep dive into the BitzOrcas.Modern seeded account catalog: the Fail-Closed environment variable password injection contract, RSA-OAEP anti-replay transport encryption, and anti-probing 404 multi-tenant isolation.

Last updated

Throughout the history of enterprise software and SaaS platforms, security breaches stemming from “hardcoded default credentials” have been recurring hazards. Many open-source platforms hardcode credentials like admin / 123456 into database seed scripts for onboarding convenience. When these systems are promoted to staging or internet-facing production environments, overlooked default accounts become primary attack vectors for supply-chain compromise and lateral privilege escalation.

BitzOrcas.Modern strictly enforces “Secure by Default and Zero-Trust” architecture. The seeding infrastructure forbids committing plaintext passwords to source control, implementing a Fail-Closed environment variable injection contract coupled with client-side RSA-OAEP asymmetric transport encryption and 404 anti-probing tenant isolation.

Account Topology & Secure Injection Architecture

The architecture isolates the tenant data plane from the host operational plane:

Fail-Closed Password Injection Pipeline

Environment Variable USER____PASSWORD
(Mapped to .NET USER::PASSWORD)

BCrypt Password Hasher (WorkFactor = 11)

SQL Server User Credentials Table

Demo Tenant Business Plane (TenantId = 1000001, LegalTech Scenario)

admin
Tenant Primary Administrator (tenant-admin)

auditor
Compliance Officer (Read-only Compliance)

operator / support
Daily Operations and Client Support

Host Operational Plane (TenantId = 0, Platform Ops & Jobs)

host-admin
Platform Super Administrator

host-ops / host-developer
Operations and Diagnostics


Privileged Super Administrator: admin / Admin@2026

The built-in super administrator seed (BuiltinIdentitySuperAdminSeedStep) is provisioned exclusively for local rapid onboarding. This step executes only in development environments for tenant 1000001:

  • Username: admin
  • Development Password: Admin@2026
  • Bound Roles: SuperAdmin (automatically aggregates all module governance permissions across the platform, including RootCrossTenant and TenantDataScope).

Production Override Precedence

In production environments, using the default password triggers a fatal startup failure. The engine evaluates administrator credentials according to the following precedence hierarchy:

Identity:SuperAdmin:Password Config Key > Parameters:demo-user-password > USER__ADMIN__PASSWORD Environment Variable > Terminate Process

If the runtime detects HostingEnvironment == Production without an explicit credential override, the seed process aborts with an unrecoverable security exception.


The Seeded Account Matrix: Fail-Closed Password Injection

Aside from the development super administrator, all tenant and host accounts in seed CSV assets store environment variable reference placeholders (e.g., from-env:USER__OPERATOR__PASSWORD).

1. Injection Specifications and Hierarchical Mapping

The resolver accepts plaintext strings for dynamic hashing as well as pre-computed BCrypt hashes:

Environment VariablePayloadRuntime Behavior
USER__<NAME>__PASSWORDPlaintext passwordThe seed engine computes a BCrypt hash (work factor 11) before persistence
USER__<NAME>__PASSWORD_HASHPre-computed BCrypt digestThe seed engine persists the digest directly, bypassing runtime hashing

2. Injection Workflow and Password Reset

Before invoking database seeding, inject account passwords in your terminal:

Inject account passwords via Bash
# Tenant 1000001 operational roles
export USER__OPERATOR__PASSWORD='Operator@2026'
export USER__SUPPORT__PASSWORD='Support@2026'
export USER__AUDITOR__PASSWORD='Auditor@2026'
# Host operational roles
export USER__HOST_ADMIN__PASSWORD='HostAdmin@2026'
export USER__HOST_OPS__PASSWORD='HostOps@2026'
  • Fail-Closed Guarantee: If the seed runner identifies an account without a corresponding environment variable, it throws InvalidOperationException and logs the missing key name. No fallback placeholder passwords are ever inserted.
  • Incremental Password Reset: By default, existing database accounts retain their current password hash during subsequent seed runs. To forcefully reset existing demo passwords to current injected variables, set:
    Terminal window
    export BITZORCAS_RESET_DEMO_PASSWORDS=true

Seeded Account Catalog & Roles

Tenant Data Plane: Demo Tenant (TenantId = 1000001)

AccountRolesOperational Domain & Access Boundary
admintenant-admin + root-adminHighest tenant administrator with full authority over cases, billing, and seats
operatoroperatorCore domain operator (e.g., LegalTech matter intake, contract creation, quota management)
supportsupport-agentFront-line support agent handling service tickets and customer chat interactions
auditorauditorCompliance auditor possessing read-only inquiry and activity audit inspection privileges
developerdeveloperSandbox engineer with OpenAPI access and diagnostic endpoint permissions

Host Operational Plane: Host Partition (TenantId = 0)

The Host partition manages platform infrastructure and tenant provisioning, holding no tenant business data:

  • host-admin: Platform root administrator.
  • host-ops: Operations engineer managing database backups, health probes, and cluster nodes.
  • host-developer: Framework engineer maintaining platform plugins and module governance.

Authentication Handshake: RSA-OAEP Encryption & Anti-Replay

BitzOrcas rejects plaintext passwords across the network wire. Clients must fetch a temporary asymmetric public key and construct a timestamped anti-replay envelope before calling login:

"User Persistence Store""IPasswordCipherService""Minimal API (/api/auth)""User Persistence Store""IPasswordCipherService""Minimal API (/api/auth)"Client constructs payload: $"{nonce}|{clientTimestamp}|{rawPassword}"Encrypts payload using RSA-OAEP-SHA256 and Base64 encodes"Web SPA / Native Client"1. GET /api/auth/cipher-key (Fetch temporary public key)12. Return RSA-OAEP-SHA256 public key, keyId, and server timestamp23. POST /api/auth/login{ userName, encryptedPassword, cipherKeyId }34. Submit ciphertext for decryption and replay inspection45. Decrypt via private key, verify clock skew (<= 300s) and nonce56. Return original sanitized plaintext password67. Verify BCrypt hash and issue JWT credentials78. Return HTTP 200 OK with TokenResponse8"Web SPA / Native Client"

End-to-End C# Integration Test

The following integration test verifies public key retrieval, RSA-OAEP encryption, and authentication using WebApplicationFactory:

using System.Net;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using BitzOrcas.Identity.Contracts.Identity.Dtos;
using Shouldly;
using Xunit;
public sealed class AuthenticationAndTenancyIntegrationTests : IClassFixture<CustomWebApplicationFactory>
{
private readonly HttpClient _client;
public AuthenticationAndTenancyIntegrationTests(CustomWebApplicationFactory factory)
{
_client = factory.CreateClient();
}
[Fact]
public async Task Login_WithRsaOaepEncryptedPassword_ShouldSucceedAndIssueJwt()
{
// 1. Fetch current active RSA-OAEP public encryption key and identifier
var keyResponse = await _client.GetFromJsonAsync<CipherPublicKeyResponse>("/api/auth/cipher-key");
keyResponse.ShouldNotBeNull();
keyResponse.PublicKeyPem.ShouldNotBeNullOrWhiteSpace();
// 2. Construct anti-replay payload: nonce|timestamp|password
var nonce = Guid.NewGuid().ToString("N");
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var rawPayload = $"{nonce}|{timestamp}|Admin@2026";
// 3. Encrypt payload via RSA-OAEP-SHA256 using server public key
using var rsa = RSA.Create();
rsa.ImportFromPem(keyResponse.PublicKeyPem);
var encryptedBytes = rsa.Encrypt(Encoding.UTF8.GetBytes(rawPayload), RSAEncryptionPadding.OaepSHA256);
var base64EncryptedPassword = Convert.ToBase64String(encryptedBytes);
// 4. Dispatch login request
var loginRequest = new LoginRequest(
UserName: "admin",
EncryptedPassword: base64EncryptedPassword,
CipherKeyId: keyResponse.KeyId);
var loginResponse = await _client.PostAsJsonAsync("/api/auth/login", loginRequest);
// 5. Machine assertion: verify HTTP 200 OK and valid JWT access token
loginResponse.StatusCode.ShouldBe(HttpStatusCode.OK);
var tokenResult = await loginResponse.Content.ReadFromJsonAsync<TokenResponse>();
tokenResult.ShouldNotBeNull();
tokenResult.AccessToken.ShouldNotBeNullOrWhiteSpace();
}
}

Multi-Tenant Isolation: Why 404 Instead of 403

In multi-tenant security architecture, a subtle vulnerability is Resource ID Enumeration Probing.

If Tenant B attempts to read a legal matter (MATTER-10029) belonging to Tenant A:

  • Flawed Pattern (HTTP 403 Forbidden): The system informs the client that access is denied. This inadvertently confirms that the resource ID exists within the database, enabling adversaries to infer business volumes or coordinate targeted reconnaissance.
  • BitzOrcas Defense (HTTP 404 Not Found): In the persistence layer (SqlSugar / EF Core), the global tenant query filter appends WHERE TenantId = CurrentTenant.Id. The SQL query returns zero matching rows. The repository handles this as an absent entity, returning a uniform 404 Not Found.
"SQL Server Database""Global Tenant Query Filter""API Host""SQL Server Database""Global Tenant Query Filter""API Host""Adversary Caller (Tenant 1000002)"GET /api/cases/MATTER-10029 (Belongs to Tenant 1000001)1Query predicate: Id = 'MATTER-10029'2Rewrite SQL: WHERE Id = 'MATTER-10029' AND TenantId = 10000023Returns 0 matched rows4EntityNotFound Result5HTTP 404 Not Found (Eliminates resource enumeration risk)6"Adversary Caller (Tenant 1000002)"

Through this defense-in-depth architecture, BitzOrcas guarantees that multi-tenant isolation boundaries remain leak-proof in both demonstration and production environments.

100%

Scroll or use controls to zoom · drag when enlarged · double-click for 100% / 200%