Portal Community

Security Layers Overview

Transport Encryption

All transports require TLS 1.2 or higher. Plaintext connections are rejected at the server level.

Connection Authentication

SignalR connections require a signed JWT. HTTP calls require a bearer token or API key. Unauthenticated connections are refused before any message is processed.

Tenant Isolation

Every message's tenantId is verified against the authenticated credential. Cross-tenant messages are silently discarded and audited.

Message Signing

Planned for ANCP 1.1 — Ed25519 signatures on the envelope header prevent message tampering in transit.

Transport Encryption (TLS)

All ANCP transports operate over TLS. The platform enforces TLS 1.2 as the minimum version, with TLS 1.3 preferred. Certificate validation is not optional — self-signed certificates are rejected in production deployments.

// ASP.NET Core — enforce HTTPS on the SignalR hub
app.UseHttpsRedirection();
app.UseHsts();

// In Kestrel configuration (appsettings.json)
{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://+:443",
        "Certificate": {
          "Subject": "*.bizfirst.io",
          "Store": "My",
          "Location": "LocalMachine"
        }
      }
    }
  }
}

Authentication

SignalR — JWT Bearer

Browser clients and server-side node hosts authenticate to the SignalR hub using a JWT bearer token. The token is attached during connection negotiation and validated before the connection is accepted. Because WebSockets cannot send HTTP headers after the upgrade, the token is passed as a query parameter during negotiation:

// Client-side connection with JWT
const connection = new HubConnectionBuilder()
  .withUrl('https://api.bizfirst.io/ancp-hub', {
    accessTokenFactory: () => getAccessToken()  // Called on each connect/reconnect
  })
  .withAutomaticReconnect([1000, 2000, 5000, 10000, 30000])
  .build();

await connection.start();
// ASP.NET Core — JWT validation for SignalR
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(options => {
    options.TokenValidationParameters = new TokenValidationParameters {
      ValidateIssuer     = true,
      ValidIssuer        = "https://identity.bizfirst.io",
      ValidateAudience   = true,
      ValidAudience      = "ancp-api",
      ValidateLifetime   = true,
      ClockSkew          = TimeSpan.Zero,
      IssuerSigningKey   = signingKey
    };
    // Allow JWT in query string for SignalR WebSocket upgrade
    options.Events = new JwtBearerEvents {
      OnMessageReceived = ctx => {
        var token = ctx.Request.Query["access_token"];
        if (!string.IsNullOrEmpty(token))
          ctx.Token = token;
        return Task.CompletedTask;
      }
    };
  });

HTTP — Bearer Token and API Keys

Server-to-server HTTP calls use a bearer JWT in the Authorization header. External integrations may use API keys scoped to a specific tenant and permission set:

POST /api/ancp/messages HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
X-Tenant-Id: tenant-acme
Content-Type: application/json

Tenant Isolation

After authentication succeeds, the router performs tenant isolation checks on every incoming message. This is enforced at the protocol layer — it does not depend on application code to remember to check.

CheckFailure ActionAudit Event
Envelope tenantId matches JWT tenantId claim Message discarded ANCP_TENANT_MISMATCH
Source URI tenantId matches envelope tenantId Message discarded ANCP_SOURCE_TENANT_MISMATCH
Destination URI tenantId matches envelope tenantId Message discarded ANCP_DEST_TENANT_MISMATCH
Topic subscription belongs to same tenant Subscription refused ANCP_CROSS_TENANT_SUBSCRIBE
Silent Drop — Not an Error Response

Cross-tenant messages are not returned to the sender with an error message. This prevents an attacker from probing which tenants exist by watching for error vs. no-response. The message is dropped silently; only the audit log records the violation.

Node Capability Authorization

Beyond tenant isolation, the ProcessSecurity layer checks that the source node or agent has the capability to send the requested message type to the destination. Capabilities are defined in the NodeCapabilityPolicy table.

// Example: Node capability check (C# — ProcessSecurity)
public async Task<bool> CanSendAsync(string sourceAddress, string destAddress, string messageType)
{
    var sourceNodeId = AncpAddress.Parse(sourceAddress).NodeId;
    var policy       = await _nodeCapabilityRepo.GetAsync(sourceNodeId);

    return policy.AllowedDestinations.Contains(destAddress)
        && policy.AllowedMessageTypes.Contains(messageType);
}

Message Signing (ANCP 1.1 — Planned)

ANCP 1.1 will introduce optional message signing using Ed25519 asymmetric keys. The signature covers the canonical form of the envelope header fields and prevents tampering in transit.

// Planned signature header format (ANCP 1.1)
{
  "id":        "msg-uuid",
  "type":      "Command",
  // ... other fields ...
  "signature": {
    "algorithm": "Ed25519",
    "keyId":     "node-signing-key-v1",
    "value":     "base64url-encoded-signature"
  }
}
DIDComm for Agent-to-Agent Encryption

For high-trust agent-to-agent communication, ANCP supports carrying DIDComm v2 encrypted payloads inside the payload field. The outer ANCP envelope handles routing and tenant isolation; the DIDComm layer provides end-to-end encryption between specific agents. See the DIDComm v2 documentation for key exchange and envelope format details.

Security Audit Trail

All security events are written to the SecurityAuditLog table in the ProcessSecurity database. Each audit entry records:

Security Checklist for Node Authors

RequirementStatus
Always set tenantId from authenticated context — never from request inputMandatory
Never log the full payload in production — it may contain PIIMandatory
Use short-lived JWT tokens (15 min TTL) with refreshMandatory
Set ttl on time-sensitive Commands to prevent replayRecommended
Set traceId from incoming request context for end-to-end tracingRecommended
Validate correlationId on Responses before trusting the dataRecommended