Configuration
All ogiri properties are prefixed with ogiri.
Properties Reference
Security Filter
| Property | Default | Description |
|---|---|---|
ogiri.security.register-filter | true | Auto-register SecurityFilterChain |
Token Behavior
| Property | Default | Description |
|---|---|---|
ogiri.auth.max-clients | 10 | Max active tokens per user |
ogiri.auth.batch-grace-seconds | 5 | Grace period before rotation |
ogiri.auth.token-lifespan-days | 14 | Token lifetime in days |
ogiri.auth.max-bearer-token-size | 8192 | Max bearer token size in bytes (DoS protection) |
ogiri.auth.register-token-service | true | Auto-register default OgiriTokenService |
Token Rotation
| Property | Default | Description |
|---|---|---|
ogiri.auth.rotate-on-write-only | false | Only rotate on POST/PUT/DELETE |
ogiri.auth.rotate-stale-seconds | 3600 | Force rotation after N seconds (0 = disabled) |
Token Cleanup
| Property | Default | Description |
|---|---|---|
ogiri.cleanup.enabled | true | Enable scheduled cleanup job |
ogiri.cleanup.interval-ms | 21600000 | Cleanup interval in milliseconds (default: 6 hours) |
ogiri.cleanup.batch-size | 1000 | Tokens deleted per batch (large dataset optimization) |
Cookie Configuration
| Property | Default | Description |
|---|---|---|
ogiri.cookies.enabled | true | Enable auth cookies |
ogiri.cookies.secure | true | Require HTTPS (WARN if false) |
ogiri.cookies.http-only | true | Prevent JS access (WARN if false) |
ogiri.cookies.same-site | Strict | SameSite attribute (Strict/Lax/None) |
ogiri.cookies.path | "/" | Cookie path |
BCrypt Comparison Cache
Caches the result of BCrypt comparisons to avoid repeated hashing for the same token.
| Property | Default | Description |
|---|---|---|
ogiri.cache.max-size | 10000 | Max cached token comparisons |
ogiri.cache.expiry-minutes | 60 | Cache entry TTL in minutes |
ogiri.cache.use-spring-cache-manager | false | Bridge an existing CacheManager bean as the token lookup cache (Tier 2) |
ogiri.cache.cache-name | ogiri-token-lookup | Name of the Spring cache to use when use-spring-cache-manager is true |
Token Lookup Cache
Caches full token entities to eliminate repeated DB reads on every authenticated request. Disabled by default. Requires ogiri-caffeine or ogiri-redis on the classpath.
| Property | Default | Description |
|---|---|---|
ogiri.lookup.type | (none) | caffeine or redis (case-insensitive) — absent means no lookup cache |
ogiri.lookup.max-size | 10000 | Max cached entities (Caffeine only) |
ogiri.lookup.expiry-minutes | 5 | Cache entry TTL in minutes (both Caffeine and Redis) |
Token Lookup Cache
Every authenticated request calls getByUserIdAndClient() — a DB read — to load the token entity. For high-traffic apps with polling endpoints, this adds up. The token lookup cache eliminates that read for the same user/client within the configured TTL window.
Choosing a Backend
| Option | How to activate | Best for |
|---|---|---|
ogiri-caffeine | ogiri.lookup.type: caffeine | Single-instance deployments, zero infrastructure |
ogiri-redis | ogiri.lookup.type: redis | Multi-instance / containerised deployments |
| Spring CacheManager bridge | ogiri.cache.use-spring-cache-manager: true | Apps that already have a CacheManager (Ehcache, Hazelcast, etc.) and don't want an extra dependency |
Custom OgiriTokenLookupCache | Provide a @Bean | Full control — required when evictAll must work immediately |
| (none) | (absent) | Default: every request hits the database |
Priority when multiple options are available: custom bean → ogiri-caffeine/ogiri-redis → Spring CacheManager bridge. The first registered bean wins; the rest are suppressed by @ConditionalOnMissingBean.
Multi-instance deployments
Caffeine is per-JVM. If you run multiple application instances, token revocations on one node are not visible to others until the cache entry expires. Use ogiri-redis when running more than one instance.
ogiri-caffeine
Add the dependency (Caffeine is included, no extra peer dep needed):
implementation("com.quantipixels.ogiri:ogiri-caffeine:2.0.0")
implementation 'com.quantipixels.ogiri:ogiri-caffeine:2.0.0'
<dependency>
<groupId>com.quantipixels.ogiri</groupId>
<artifactId>ogiri-caffeine</artifactId>
<version>2.0.0</version>
</dependency>
Activate in application.yml:
ogiri:
lookup:
type: caffeine
max-size: 10000
expiry-minutes: 5
ogiri-redis
Add both the Ogiri Redis module and the Spring Data Redis starter (peer dependency):
implementation("com.quantipixels.ogiri:ogiri-redis:2.0.0")
implementation("org.springframework.boot:spring-boot-starter-data-redis")
implementation 'com.quantipixels.ogiri:ogiri-redis:2.0.0'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
<dependency>
<groupId>com.quantipixels.ogiri</groupId>
<artifactId>ogiri-redis</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Activate in application.yml (your existing spring.data.redis.* config is reused automatically):
spring:
data:
redis:
host: localhost
port: 6379
ogiri:
lookup:
type: redis
expiry-minutes: 5
Spring CacheManager Bridge
If your application already has a CacheManager bean configured — through Ehcache, Hazelcast, JCache, Infinispan, or simply spring.cache.type=redis — you can reuse it as the Ogiri token lookup cache without adding ogiri-caffeine or ogiri-redis.
Enable the bridge in application.yml:
spring:
cache:
cache-names: ogiri-token-lookup # must declare the cache name explicitly
redis: # example: Redis-backed CacheManager
time-to-live: 300000 # 5 minutes in ms
ogiri:
cache:
use-spring-cache-manager: true
cache-name: ogiri-token-lookup # must match a name in spring.cache.cache-names
Backend compatibility — any CacheManager implementation works. Ogiri only calls Cache.get(), Cache.put(), and Cache.evict(), which are supported by all backends.
evictAll is a no-op on this tier
Spring's Cache interface has no pattern-based eviction. When all sessions for a user are revoked (e.g. "log out everywhere"), evictAll(userId) logs a WARN and returns without clearing the cache. Stale entries expire when the TTL elapses. For immediate user-wide eviction, use ogiri-redis or provide a custom OgiriTokenLookupCache bean.
Cache name not declared
If ogiri.cache.cache-name does not appear in spring.cache.cache-names, the adapter throws IllegalStateException on first cache access. Backends that auto-create caches on demand (Caffeine, simple in-memory) do not require the name to be pre-declared.
The bridge is inactive when ogiri-caffeine or ogiri-redis is on the classpath — the dedicated module takes precedence via @ConditionalOnMissingBean.
Custom Cache
Provide your own OgiriTokenLookupCache<T> bean and neither autoconfiguration activates:
@Component
class MyCustomTokenCache : OgiriTokenLookupCache<MyToken> {
override fun get(userId: Long, client: String): MyToken? = TODO()
override fun put(userId: Long, client: String, token: MyToken) = TODO()
override fun evict(userId: Long, client: String) = TODO()
override fun evictAll(userId: Long) = TODO()
}
No ogiri.lookup.type property is required when supplying a custom bean.
Configuration Examples
Basic Setup
ogiri:
security:
register-filter: true
auth:
max-clients: 10
batch-grace-seconds: 5
token-lifespan-days: 14
max-bearer-token-size: 8192
register-token-service: true
cleanup:
enabled: true
interval-ms: 21600000 # 6 hours
batch-size: 1000
cache:
max-size: 10000
expiry-minutes: 60
# lookup.type is absent by default — no entity cache
cookies:
enabled: true
secure: true
http-only: true
same-site: Strict
path: "/"
High Security
Frequent rotation, short tokens, strict limits:
ogiri:
auth:
max-clients: 5
batch-grace-seconds: 1
token-lifespan-days: 7
max-bearer-token-size: 4096 # Stricter limit
rotate-on-write-only: false
rotate-stale-seconds: 3600 # Force rotation every hour
cleanup:
interval-ms: 3600000 # 1 hour
batch-size: 500
cookies:
enabled: true
secure: true
http-only: true
same-site: Strict
High Performance
Longer tokens, less rotation:
ogiri:
auth:
max-clients: 50
batch-grace-seconds: 30
token-lifespan-days: 30
rotate-on-write-only: true # Only rotate on writes
rotate-stale-seconds: 0 # No forced rotation
Development
Lenient settings for testing:
ogiri:
auth:
max-clients: 100
batch-grace-seconds: 60
token-lifespan-days: 30
cleanup:
enabled: false # Keep test tokens
cookies:
secure: false # Allow HTTP in development
Startup Warnings
The library logs warnings at startup for potentially insecure configurations:
| Configuration | Warning |
|---|---|
ogiri.auth.rotate-stale-seconds=0 | Time-based rotation disabled; consider setting to 3600 or higher |
ogiri.cookies.secure=false | Enable for HTTPS deployments |
ogiri.cookies.http-only=false | Enable to prevent XSS cookie theft |
ogiri.lookup.type=<unknown> | Unrecognized value; no lookup cache will be activated |
These warnings are informational and do not prevent the application from starting. They help identify security misconfigurations in production environments.
Custom Beans
Custom OgiriTokenService
If you provide your own OgiriTokenService, Ògiri will not create its default token service.
If you intentionally have multiple OgiriTokenService beans, mark exactly one as @Primary or inject by @Qualifier to avoid ambiguity.
@Configuration
class CustomConfig(private val properties: OgiriConfigurationProperties) {
@Bean
fun tokenService(
tokenRepository: OgiriTokenRepository<MyToken>,
passwordEncoder: PasswordEncoder,
ogiriUserDirectory: OgiriUserDirectory,
identifierPolicy: IdentifierPolicy,
subTokenRegistry: OgiriSubTokenRegistry,
auditHook: ObjectProvider<OgiriAuditHook>,
rateLimitHook: ObjectProvider<OgiriRateLimitHook>,
lookupCache: ObjectProvider<OgiriTokenLookupCache<MyToken>>,
): OgiriTokenService<MyToken> {
val service = MyCustomTokenService(
tokenRepository,
passwordEncoder,
ogiriUserDirectory,
identifierPolicy,
subTokenRegistry,
properties,
)
auditHook.ifAvailable { service.setAuditHook(it) }
rateLimitHook.ifAvailable { service.setRateLimitHook(it) }
lookupCache.ifAvailable { service.setLookupCache(it) }
return service
}
}
Custom SecurityFilterChain
Disable auto-configuration:
ogiri:
security:
register-filter: false
Then provide your own:
@Configuration
class SecurityConfig {
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
return http
.authorizeRequests { it.anyRequest().authenticated() }
.addFilter(OgiriTokenAuthenticationFilter(tokenService, authBypassDecider))
.build()
}
}
Properties File Format
ogiri.security.register-filter=true
ogiri.auth.max-clients=10
ogiri.auth.batch-grace-seconds=5
ogiri.auth.token-lifespan-days=14
ogiri.auth.max-bearer-token-size=8192
ogiri.auth.rotate-on-write-only=false
ogiri.auth.rotate-stale-seconds=3600
ogiri.auth.register-token-service=true
ogiri.cleanup.enabled=true
ogiri.cleanup.interval-ms=21600000
ogiri.cleanup.batch-size=1000
ogiri.cookies.enabled=true
ogiri.cookies.secure=true
ogiri.cookies.http-only=true
ogiri.cookies.same-site=Strict
ogiri.cookies.path=/
Troubleshooting
| Issue | Solution |
|---|---|
| Token expires immediately | Increase token-lifespan-days |
| Tokens rotate too frequently | Increase batch-grace-seconds |
| Too many active tokens | Decrease max-clients |
| Tests fail with token mismatch | Set ogiri.cleanup.enabled=false in test profile |