Your token expiry enforcement issue stems from three interconnected problems in the oiot-23 security architecture:
Token Expiry Enforcement:
The platform’s API gateway uses a two-tier validation strategy that causes expired tokens to remain valid longer than configured. First-tier validation checks token signature and basic structure, but expiry validation is deferred to second-tier database lookup, which is cached aggressively.
To enforce strict expiry, configure the gateway to validate JWT claims on every request:
{
"gatewayPolicy": {
"tokenValidation": {
"validateExpiry": true,
"cacheValidation": false,
"enforceClockSkew": 60
}
}
}
Set cacheValidation to false to disable validation caching. This increases latency by 20-50ms per request but ensures real-time expiry enforcement. The enforceClockSkew parameter (in seconds) accounts for time synchronization differences between servers.
For opaque (non-JWT) tokens, enable database validation on every request:
SecurityConfig config = new SecurityConfig();
config.setTokenValidationMode("REALTIME");
config.setCacheTokenValidation(false);
securityClient.updateConfig(config);
Revocation List Polling:
The SDK’s default revocation list polling interval (30 minutes) is too long for security-critical applications. Expired tokens should be automatically added to the revocation list, but oiot-23 doesn’t do this by default - it only tracks manually revoked tokens.
Implement automatic expiry-based revocation:
// Scheduled job to revoke expired tokens
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
List<Token> expiredTokens = securityClient.getExpiredTokens();
for (Token token : expiredTokens) {
securityClient.revokeToken(token.getId(), "EXPIRED");
}
}, 0, 5, TimeUnit.MINUTES);
Run this job every 5 minutes to move expired tokens to the revocation list. This ensures they’re blocked even if validation caching is enabled.
Configure SDK revocation list polling for more frequent updates:
SDKConfig sdkConfig = new SDKConfig();
sdkConfig.setRevocationListPollInterval(300); // 5 minutes
sdkConfig.setRevocationListCacheEnabled(false);
Disabling the revocation list cache forces the SDK to fetch the latest list on every validation.
SDK Validation Logic:
The SDK’s client-side validation doesn’t check token expiry by default - it relies on server-side validation. For defense-in-depth, implement client-side expiry validation:
public boolean isTokenValid(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
Date expiry = jwt.getExpiresAt();
if (expiry.before(new Date())) {
logger.warn("Token expired: {}", token);
return false;
}
// Check against revocation list
if (securityClient.isTokenRevoked(jwt.getId())) {
logger.warn("Token revoked: {}", token);
return false;
}
return true;
} catch (JWTDecodeException e) {
return false;
}
}
Call this validation before every API request to catch expired tokens before they reach the server.
Additional Security Measures:
For compliance audit requirements, implement token rotation:
// Rotate tokens before expiry
if (token.getExpiresAt().getTime() - System.currentTimeMillis() < 3600000) {
// Less than 1 hour until expiry - rotate
Token newToken = securityClient.rotateToken(token.getId());
// Update client configuration with new token
}
Enable audit logging for token validation failures:
AuditConfig auditConfig = new AuditConfig();
auditConfig.setLogExpiredTokenAttempts(true);
auditConfig.setLogRevocationChecks(true);
securityClient.updateAuditConfig(auditConfig);
This creates an audit trail of expired token usage attempts, which is critical for compliance.
Implementing these three layers - gateway-level expiry enforcement, automatic revocation of expired tokens, and client-side validation - ensures strict token expiry enforcement that meets security audit requirements.