Portal Community

Authentication

The Multi-Query API uses standard BizFirst JWT Bearer authentication. Tokens are validated on every request using the following settings:

Setting Value Config Key
ValidateIssuer true JWT:Issuer
ValidateAudience true JWT:Audience
ValidateLifetime true
ClockSkew 5 minutes
Signing key HMAC-SHA256 JWT:Key

All requests must include the token in the Authorization header:

Authorization: Bearer <your-jwt-token>

Authorization

Every Multi-Query controller action is decorated with [AuthorizeTenantAdminAttribute]. This attribute enforces that the authenticated principal holds at least one of the following roles:

Requests from users without either role receive an HTTP 403 Forbidden response immediately after token validation, before any template or database logic executes. Standard user roles (Employee, Manager, etc.) do not have access to any Multi-Query endpoint.

// Applied to all Multi-Query controller actions
[AuthorizeTenantAdminAttribute]
[ApiLimit("MultiQuery.Execute")]
public async Task<IActionResult> ExecuteJson(string templateCode) { ... }

Tenant Isolation

Hard tenant boundary — enforced at every level

The TenantID used to scope all SQL execution is extracted exclusively from the JWT claim CurrentTenantIDWithCheck_Int. It is injected into the root query and every child query in the tree. Callers cannot supply, influence, or override the TenantID through request parameters, body fields, template parameters, or expression context values.

This guarantee applies even to the run-direct endpoint: if the submitted SQL references @TenantID, that parameter is bound to the JWT-derived value — the caller cannot change it. Attempts to reference a different tenant's data are blocked at the SQL parameter binding layer.

Template authors should always include a WHERE TenantID = @TenantID clause in their root and child queries. The engine injects the value; the SQL must consume it.

Rate Limiting

Each operation class has its own rate limit bucket, configured via ApiLimit attributes. Limits are applied per-tenant and per-user. Exceeding the limit returns HTTP 429 Too Many Requests.

Endpoint Rate Limit Key Limit Type
GET …/multiquery/{code}
GET …/{code}.json
GET …/{code}.html
ApiLimit("MultiQuery.Execute") eOperationLimitType.Custom
POST …/scripts/run-stored ApiLimit("MultiQuery.RunStoredScript") Default
POST …/scripts/run-direct ApiLimit("MultiQuery.RunDirectScript") Default

Rate limit thresholds are configured in platform settings and can be adjusted per-environment. The eOperationLimitType.Custom designation on the Execute endpoints allows the platform administrator to set a higher ceiling for read-heavy reporting use cases.

Template SQL Security

Templates stored in dbo.Shared_Configurations are trusted SQL authored by platform administrators. The following rules govern what is permitted:

Audit Trail

All requests are platform-logged
Every call to a Multi-Query endpoint passes through the BizFirst standard request logging pipeline. The log entry includes the authenticated user identity, TenantID, endpoint path, template code (when applicable), HTTP status code, and execution duration. Include an X-Request-ID header in your requests to correlate client-side traces with platform log entries.

CORS

The platform is configured with an AllowAll CORS policy in development and staging environments for ease of integration testing. In production environments you must restrict CORS to specific trusted origins:

// Production configuration — restrict to known origins
builder.Services.AddCors(options => {
    options.AddPolicy("MultiQueryPolicy", policy => {
        policy.WithOrigins(
            "https://app.bizfirstai.com",
            "https://admin.bizfirstai.com"
        )
        .AllowAnyHeader()
        .AllowAnyMethod();
    });
});
Run-Direct: Elevated Risk
The POST …/scripts/run-direct endpoint executes arbitrary SQL text submitted in the request body. While TenantID is always injected from the JWT, a poorly written query could expose large volumes of tenant data or cause performance degradation. Ensure that only highly trusted administrators hold the TenantAdmin role in production environments. Consider disabling the run-direct endpoint entirely in customer-facing deployments and reserving it for internal tooling only.