Complete Guide to Built-in ConditionMatchers in CoSec
CoSec provides 16 built-in ConditionMatchers ranging from path matching and role-based access control to rate limiting and expression evaluation, all implementing the ConditionMatcherFactory interface and auto-registered via ConditionMatcherFactoryProvider.
The ahoo-wang/cosec repository ships with a comprehensive set of built-in ConditionMatchers that enable developers to express complex authorization policies without writing custom Kotlin or Java code. Each matcher is instantiated through a factory pattern and automatically discovered by the Spring Boot starter, allowing immediate use in JSON or YAML policy definitions.
Logical Combinators and Context Matchers
These matchers handle boolean logic and security context validation, forming the foundation for role-based and multi-tenant access control policies.
AllConditionMatcher
Type: all
The AllConditionMatcher (implemented in AllConditionMatcherFactory.kt) returns true for every request. Use this as a catch-all or default policy condition.
{
"type": "all"
}
BoolConditionMatcher
Type: bool
The BoolConditionMatcher (implemented in BoolConditionMatcherFactory.kt) provides logical composition via and and or arrays, allowing nested conditions without custom code.
{
"type": "bool",
"and": [
{ "type": "authenticated" },
{ "type": "path", "path": "/api/**" }
]
}
AuthenticatedConditionMatcher
Type: authenticated
Located in AuthenticatedConditionMatcherFactory.kt, this matcher verifies that the current SecurityContext contains an authenticated principal.
{
"type": "authenticated"
}
InTenantConditionMatcher
Type: inTenant
Implemented in InTenantConditionMatcherFactory.kt, this matcher checks if the current tenant ID exists within a configured list.
{
"type": "inTenant",
"tenants": ["tenant-a", "tenant-b"]
}
InRoleConditionMatcher
Type: inRole
The InRoleConditionMatcher (source: InRoleConditionMatcherFactory.kt) validates that the authenticated principal possesses at least one role from the supplied array.
{
"type": "inRole",
"roles": ["ADMIN", "OPERATOR"]
}
HTTP Request Part Matchers
These matchers operate on specific attributes of the HTTP request, such as the URI path or header values.
PathConditionMatcher
Type: path
Defined in PathConditionMatcherFactory.kt, this matcher supports Ant-style patterns (e.g., /admin/**) and regular expressions against the request URI.
{
"type": "path",
"path": "/admin/**"
}
StartsWithConditionMatcher
Type: startsWith
Located in StartsWithConditionMatcherFactory.kt, this checks whether a string part (path, header, etc.) begins with a configured value. Supports case-insensitive matching via a boolean flag.
{
"type": "startsWith",
"part": "path",
"value": "/api/v1",
"ignoreCase": true
}
EndsWithConditionMatcher
Type: endsWith
Implemented in EndsWithConditionMatcherFactory.kt, this matcher verifies suffix matches on request parts.
{
"type": "endsWith",
"part": "uri",
"value": ".json"
}
ContainsConditionMatcher
Type: contains
The ContainsConditionMatcher (source: ContainsConditionMatcherFactory.kt) checks for substring presence within a request attribute.
{
"type": "contains",
"part": "userAgent",
"value": "Mobile"
}
EqConditionMatcher
Type: eq
Located in EqConditionMatcherFactory.kt, this performs strict equality checks with optional case insensitivity.
{
"type": "eq",
"part": "method",
"value": "GET",
"ignoreCase": false
}
InConditionMatcher
Type: in
Implemented in InConditionMatcherFactory.kt, this matcher checks if a string part exists within a supplied set of values.
{
"type": "in",
"part": "header:X-Client-Type",
"values": ["web", "mobile", "api"]
}
RegularConditionMatcher
Type: regex
The RegularConditionMatcher (source: RegularConditionMatcherFactory.kt) applies Java regular expressions to request parts for complex pattern matching.
{
"type": "regex",
"part": "path",
"pattern": "^/api/v[0-9]+/.*$"
}
Expression Evaluation Matchers
For scenarios requiring dynamic evaluation beyond static pattern matching, CoSec integrates two expression languages.
SpELConditionMatcher
Type: spel
The SpELConditionMatcher (implemented in SpelConditionMatcherFactory.kt) evaluates Spring Expression Language expressions against the request context and security attributes.
{
"type": "spel",
"expression": "#request.headers['X-Api-Key'] == 'secret'"
}
OGNLConditionMatcher
Type: ognl
Located in OgnlConditionMatcherFactory.kt, this matcher uses OGNL (Object-Graph Navigation Language) for expression-based matching in non-Spring environments or legacy integrations.
{
"type": "ognl",
"expression": "request.method == 'POST'"
}
Rate Limiting and Throttling Matchers
These matchers enforce traffic control policies at the policy level, independent of external gateway configurations.
RateLimiterConditionMatcher
Type: rateLimiter
Implemented in RateLimiterConditionMatcherFactory.kt, this matcher restricts requests per time window based on a configurable key extractor (e.g., client IP).
{
"type": "rateLimiter",
"key": "clientIp",
"limit": 100,
"duration": "1m"
}
GroupedRateLimiterConditionMatcher
Type: groupedRateLimiter
The GroupedRateLimiterConditionMatcher (source: GroupedRateLimiterConditionMatcherFactory.kt) extends rate limiting to support distinct limits per group (tenant, user, or custom attribute).
{
"type": "groupedRateLimiter",
"groupKey": "tenantId",
"limit": 1000,
"duration": "1h"
}
How Built-in Matchers Are Registered and Executed
Understanding the lifecycle of ConditionMatchers ensures proper debugging and extension.
Factory Registration
Upon Spring context startup, MatcherFactoryRegister (located in cosec-spring-boot-starter/src/main/kotlin/me/ahoo/cosec/spring/boot/starter/policy/MatcherFactoryRegister.kt) scans for all beans implementing ConditionMatcherFactory. It registers each discovered factory with the ConditionMatcherFactoryProvider singleton using the factory's type constant as the lookup key.
Policy Deserialization
When parsing policy JSON or YAML, JsonConditionMatcherSerializer (in cosec-core/src/main/kotlin/me/ahoo/cosec/serialization/JsonConditionMatcherSerializer.kt) extracts the type field, retrieves the corresponding factory via ConditionMatcherFactoryProvider.getRequired(type), and invokes the factory's create method to instantiate the matcher.
Runtime Evaluation
At request time, the AuthorizationGatewayFilter (or servlet filter) calls ConditionMatcher.match(request, securityContext). The concrete implementation—whether PathConditionMatcher, InRoleConditionMatcher, or SpelConditionMatcher—executes its specific logic against the request attributes and returns a boolean result.
Practical Policy Configuration Examples
Complex Boolean Logic
Combine multiple matchers using the bool type to enforce multi-factor authorization:
{
"policyId": "secure-admin-api",
"condition": {
"type": "bool",
"and": [
{ "type": "authenticated" },
{
"type": "bool",
"or": [
{ "type": "inRole", "roles": ["ADMIN"] },
{ "type": "inRole", "roles": ["SUPERUSER"] }
]
},
{ "type": "path", "path": "/admin/api/**" }
]
},
"action": {
"type": "allow"
}
}
Multi-Tenant Rate Limiting
Apply per-tenant request throttling using the grouped rate limiter:
{
"policyId": "tenant-throttle",
"condition": {
"type": "groupedRateLimiter",
"groupKey": "tenantId",
"limit": 500,
"duration": "5m"
},
"action": {
"type": "allow"
}
}
SpEL-Based Dynamic Checks
Use Spring expressions for header validation without custom code:
{
"policyId": "api-key-check",
"condition": {
"type": "spel",
"expression": "#request.headers['X-API-Version'] matches '2\\\\.0'"
},
"action": {
"type": "allow"
}
}
Summary
- CoSec includes 16 built-in ConditionMatchers covering logical operations, context validation, string pattern matching, expression evaluation, and rate limiting.
- Each matcher follows the Factory pattern, implementing
ConditionMatcherFactoryand registering automatically viaConditionMatcherFactoryProvider. - Source files are organized by function: context matchers reside in
policy/condition/context/, part matchers inpolicy/condition/part/, and limiters inpolicy/condition/limiter/. - Policy definitions use the
typefield to reference factories, with configuration parameters specific to each matcher implementation. - Extension is straightforward: implement
ConditionMatcherFactoryas a Spring bean to add custom matchers alongside built-ins.
Frequently Asked Questions
How do I create a custom ConditionMatcher in CoSec?
Implement the ConditionMatcherFactory interface and define a unique type constant. Register your implementation as a Spring bean (e.g., using @Component). The MatcherFactoryRegister will automatically discover and register it with ConditionMatcherFactoryProvider, making it available in policy JSON using your custom type.
What is the difference between the bool and all matchers?
The all matcher (type: all) is a constant matcher that always returns true, useful for default allow/deny policies. The bool matcher (type: bool) is a logical combinator that evaluates nested and or or arrays of other matchers, enabling complex boolean logic without writing code.
When should I use SpEL versus OGNL expression matchers?
Use SpEL (type: spel) when running CoSec within a Spring ecosystem, as it provides tight integration with Spring's bean context and security expressions. Use OGNL (type: ognl) for lightweight deployments or non-Spring environments where you need expression evaluation without Spring dependencies.
How does groupedRateLimiter differ from the standard rateLimiter?
The standard rateLimiter (type: rateLimiter) applies a single global limit based on a key (like client IP). The groupedRateLimiter (type: groupedRateLimiter) maintains separate rate-limit counters per distinct group value (like tenant ID or user ID), allowing you to enforce "100 requests per minute per user" rather than "100 requests per minute total."
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →