Java API Integration
This section documents how the CWMS Data API integrates with the Authorization Proxy to enforce access control at the database level.
Overview
The authorization architecture follows a clear separation of concerns:
flowchart LR
subgraph Proxy
A[Authorization Proxy]
B[OPA Policy Engine]
end
subgraph JavaAPI[Java API]
C[AuthorizationContextHelper]
D[AuthorizationFilterHelper]
E[JOOQ Query Builder]
end
subgraph Database
F[Oracle DB]
end
A --> B
B --> A
A -->|x-cwms-auth-context| C
C --> D
D --> E
E --> F
Key Principle
The Authorization Proxy makes authorization decisions and passes filtering constraints to the Java API via the x-cwms-auth-context header. The Java API does not make authorization decisions. Instead, it applies the constraints at the database query level to filter results.
Component |
Responsibility |
|---|---|
Authorization Proxy |
Makes allow/deny decisions via OPA |
OPA Policy Engine |
Evaluates policies, determines constraints |
AuthorizationContextHelper |
Parses header, provides user context |
AuthorizationFilterHelper |
Generates JOOQ conditions from constraints |
Database |
Returns filtered results |
Helper Classes
The Java API provides two helper classes for integration:
Integration Flow
sequenceDiagram
participant Client
participant Proxy as Authorization Proxy
participant OPA
participant API as Java API
participant DB as Oracle DB
Client->>Proxy: Request with JWT
Proxy->>OPA: Evaluate policy
OPA-->>Proxy: Decision + constraints
Proxy->>API: Request + x-cwms-auth-context
API->>API: Parse header (ContextHelper)
API->>API: Build filters (FilterHelper)
API->>DB: Query with WHERE conditions
DB-->>API: Filtered results
API-->>Proxy: Response
Proxy-->>Client: Response
Usage in Controllers
Controllers integrate authorization filtering by:
Creating helper instances from the Javalin context
Extracting relevant filter conditions
Applying conditions to JOOQ queries
public class TimeSeriesController extends BaseHandler {
@Override
public void handle(Context ctx) {
AuthorizationContextHelper authContext = new AuthorizationContextHelper(ctx);
AuthorizationFilterHelper filterHelper = new AuthorizationFilterHelper(ctx);
String requestedOffice = ctx.queryParam("office");
// Build query with authorization filters
Condition authFilters = filterHelper.getAllFilters(
TIMESERIES.OFFICE_ID,
TIMESERIES.DATE_TIME,
TIMESERIES.CLASSIFICATION,
requestedOffice,
userRequestedBeginTime
);
// Apply filters to query
List<TimeSeries> results = dsl.selectFrom(TIMESERIES)
.where(authFilters)
.fetch();
}
}