Skip to content

Security

František Bereň edited this page Sep 18, 2026 · 2 revisions

Security

Tokens, password hashing, and somewhere safe to keep secrets.

Project For
Birko.Security core contracts
.Jwt issue and validate JWTs
.BCrypt password hashing
.OAuth.Server be an OAuth provider
.Vault, .Vault.Configuration HashiCorp Vault secrets
.AzureKeyVault Azure Key Vault secrets
.AspNetCore ASP.NET integration
.NFC NFC-based authentication

JWT

// provider: JwtTokenProvider, built from your JwtSettings

var token = provider.GenerateToken(new Dictionary<string, string>
{
    ["sub"]    = userId.ToString(),
    ["tenant"] = tenantId.ToString(),
});

var result = provider.ValidateToken(token.Token);
if (result.IsValid)
{
    var sub = result.Claims["sub"];
}

TokenOptions on either call overrides lifetime and similar per token.

Passwords

var hash = hasher.Hash(plainPassword);
var ok   = hasher.Verify(plainPassword, hash);

Never store the plain value, and never compare hashes with == — Verify exists because the comparison has to be constant-time.

Secrets

Both Vault and Azure Key Vault expose the same provider shape, so which one you use is configuration:

var secret  = await secretProvider.GetSecretAsync("Db:Password");
var secrets = await secretProvider.ListSecretsAsync();

Birko.Security.Vault.Configuration plugs Vault into IConfiguration, so secrets arrive as ordinary configuration values.

Multi-tenancy

Tenant isolation lives in the data layer (Birko.Data.Tenant) rather than here, but it is a security boundary and worth stating plainly:

⚠️ The tenant wrappers fail open when no tenant is resolved. That is deliberate — a system operation legitimately has no tenant — but it means anything that resolves a tenant must publish it via ResolvedTenant.Publish(context, guid, source). A source that does not publish is a source the correlation guard cannot see, and it will not complain.

If you use tenancy, scope the read, not just the write. A tenant term on writes alone leaves reads, counts, previews and deletes operating across every tenant.

Practical notes

  • Rotate anything that reaches a config file. appsettings.Development.json should be gitignored and usually is — check yours.
  • A URI that parses is not a URL you trust. On Unix, /some/path parses as an absolute file: URI. If you mean an HTTPS endpoint, check the scheme, not just that parsing succeeded.

Next

Clone this wiki locally