Loading…
Loading…
Explains how the Tenant Context Filter identifies the tenant for each API request, populates a security context, and handles authentication failures.
The TenantContextFilter is a servlet filter that runs at the highest precedence for every incoming request to the runtime data plane. Its primary function is to establish tenant identity before any other request processing occurs.
The filter inspects incoming request attributes to determine which tenant is making the call. It relies on a pluggable TenantResolver component to perform the actual lookup and authentication. Upon successful identification, the filter populates a thread-local TenantContext with the tenant's unique ID. This context is then available to all downstream components, such as controllers and data repositories, for the duration of the request.
To prevent context leakage across requests in a multi-threaded environment, the filter guarantees that the TenantContext is cleared after each request completes, regardless of whether it succeeded or failed.
The filter's behavior depends on the platform's licensing:
The TenantContextFilter intercepts every request at the earliest stage of processing. Its execution flow is designed to be both secure and efficient.
flowchart TD
subgraph TenantContextFilter
A[Incoming Request] --> B{Is path excluded?};
B -- Yes --> C[Pass to next filter];
B -- No --> D[Build TenantResolutionContext];
D --> E[TenantResolver];
E --> F{Tenant authenticated?};
F -- Yes --> G[Set TenantContext on thread];
F -- No --> H[Short-circuit with 401/403 error];
end
G --> I[Downstream Business Logic];
I --> J[Clear TenantContext];
J --> K[Response];
H --> K;
C --> K;
style H fill:#f9e5e5,stroke:#b33,stroke-width:2pxPath Exclusion Check: Upon receiving a request, the filter first checks if the request URI matches a pattern in its exclusion list (see Excluded Paths). If a match is found, the filter immediately passes the request to the next filter in the chain without performing any tenant resolution. This is a fail-open decision used for specific internal endpoints that have their own authentication or are not tenant-scoped.
Tenant Resolution: If the path is not excluded, the filter proceeds to identify the tenant.
TenantResolutionContext object containing the Host header, the request URI, and the value of the X-S2R-Tenant-Key header.TenantResolver component.Handling Resolution Outcome:
TenantResolver returns a unique tenant ID (UUID). The filter binds this ID to the current request thread by calling TenantContext.set(). The request is then passed down the filter chain for normal processing. A finally block ensures that TenantContext.clear() is called after the request has been fully handled, preventing the tenant ID from being inadvertently reused by another request on the same thread.TenantResolver may throw a TenantAuthenticationException if authentication fails. The filter catches this exception and immediately halts further processing of the request. It generates and sends a 401 Unauthorized or 403 Forbidden error response directly to the client.To prevent security vulnerabilities such as path-traversal bypass, the filter normalizes the request path before checking it against the exclusion list. It strips semicolon path parameters and rejects any path that contains .. or // segments from the exclusion logic, ensuring that the check is performed on the same path that the framework uses for routing.
In a multi-tenant deployment, the filter enforces tenant authentication. API consumers must provide valid credentials with each request.
| Header | Required | Description |
|---|---|---|
X-S2R-Tenant-Key | Yes | The API key associated with the tenant. |
If tenant authentication fails, the filter short-circuits the request and returns a JSON error payload. The HTTP status code indicates the nature of the failure.
All authentication errors from this filter return a JSON body with the following structure. The reason field provides a machine-readable identifier for the specific failure.
{
"error": {
"code": "S2R-RUN-0401",
"message": "Tenant authentication failed",
"reason": "<REASON_ENUM_NAME>"
}
}
| Status Code | reason | Description |
|---|---|---|
401 Unauthorized | MISSING_KEY | The X-S2R-Tenant-Key header was not present in the request. |
401 Unauthorized | INVALID_KEY | The value provided in the X-S2R-Tenant-Key header is not a valid key. |
403 Forbidden | UNRESOLVED_SLUG | The tenant identifier (slug) in the request's hostname or path could not be found. |
403 Forbidden | TENANT_MISMATCH | The provided API key is valid but does not belong to the tenant identified by the request's slug. |
403 Forbidden | REVOKED | The tenant account or the specific API key has been revoked or disabled. |
Certain URL paths are explicitly excluded from tenant authentication. Requests to these paths bypass the TenantResolver logic entirely.
WARNING
The exclusion of a path is a fail-open decision that bypasses tenant authentication. This list is intentionally minimal and contains only paths for platform-internal services that do not operate within a tenant's context.
| Path Pattern | Reason for Exclusion |
|---|---|
/relay/v1/** | Used by the relay agent, which authenticates with a separate X-S2R-Relay-Key credential. The controller handling these requests performs its own authentication and tenant binding. |
/actuator/** | Used for platform health checks and operational monitoring. These endpoints are called by internal infrastructure, not by tenants, and therefore do not carry tenant credentials. Excluding them prevents liveness and readiness probes from failing with authentication errors. |