quarkusio/quarkus · error · AuthenticationCompletionException
State cookie value for the %s tenant can not be encrypted: %
Error message
State cookie value for the %s tenant can not be encrypted: %s
What it means
When the state cookie encryption key is configured, Quarkus encrypts the state cookie JSON before sending it to the browser. If OidcUtils.encryptJson fails (wrong key format/algorithm/JCE issue), the code flow cannot proceed securely, so an AuthenticationCompletionException wrapping the cause is thrown.
Source
Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java:1429
private String encodeExtraStateValue(CodeAuthenticationStateBean extraStateValue, TenantConfigContext configContext) {
JsonObject json = new JsonObject();
if (extraStateValue.getCodeVerifier() != null || extraStateValue.getNonce() != null) {
if (extraStateValue.getCodeVerifier() != null) {
json.put(OidcConstants.PKCE_CODE_VERIFIER, extraStateValue.getCodeVerifier());
}
if (extraStateValue.getNonce() != null) {
json.put(OidcConstants.NONCE, extraStateValue.getNonce());
}
if (extraStateValue.getRestorePath() != null) {
json.put(OidcUtils.STATE_COOKIE_RESTORE_PATH, extraStateValue.getRestorePath());
}
try {
return OidcUtils.encryptJson(json, configContext.getStateCookieEncryptionKey());
} catch (Exception ex) {
LOG.errorf("State cookie value for the %s tenant can not be encrypted: %s",
configContext.oidcConfig().tenantId().get(), ex.getMessage());
throw new AuthenticationCompletionException(ex);
}
} else {
json.put(OidcUtils.STATE_COOKIE_RESTORE_PATH, extraStateValue.getRestorePath());
return Base64.getUrlEncoder().withoutPadding().encodeToString(json.encode().getBytes(StandardCharsets.UTF_8));
}
}
private String generatePostLogoutState(RoutingContext context, TenantConfigContext configContext) {
OidcUtils.removeCookie(context, configContext.oidcConfig(), getPostLogoutCookieName(configContext.oidcConfig()));
return OidcUtils.createCookie(context, configContext.oidcConfig(), getPostLogoutCookieName(configContext.oidcConfig()),
UUID.randomUUID().toString(),
60 * 30).getValue();
}
private String buildUri(RoutingContext context, boolean forceHttps, String path) {
if (path.startsWith(HTTP_SCHEME)) {View on GitHub (pinned to e1c734241f)
Solutions
- Check the logged ex.getMessage() for the underlying crypto error and fix the key format (a base64-encoded key of the required AES length, e.g. 16/24/32 bytes).
- Regenerate the key: openssl rand -base64 32 and set it as the state cookie encryption secret.
- Ensure all nodes in the cluster share the identical, valid key.
- Alternatively, disable state cookie encryption if your security posture allows unencrypted (still signed/encoded) state cookies.
Example fix
// before quarkus.oidc.state-cookie-encryption-key=my-secret // after quarkus.oidc.state-cookie-encryption-key=<base64 of 32 random bytes>
Defensive patterns
Strategy: validation
Validate before calling
String key = System.getenv("QUARKUS_OIDC_STATE_COOKIE_ENCRYPTION_KEY");
byte[] raw = Base64.getDecoder().decode(key);
if (raw.length != 16 && raw.length != 24 && raw.length != 32) {
throw new IllegalStateException("State cookie encryption key must be base64 of 16/24/32 bytes, got " + raw.length);
} Try / catch
try {
return buildStateCookie(state);
} catch (AuthenticationCompletionException e) {
if (e.getCause() != null) {
log.errorf("State cookie encryption failed: %s; check key format/length", e.getCause().getMessage());
}
throw e;
} Prevention
- Generate keys with `openssl rand -base64 32` and store them in a secret manager.
- Ensure identical keys on every cluster node.
- Validate key material (length, base64 encoding) in a startup health check.
- Beware of shell/env quoting adding whitespace to the key value.
When it happens
Trigger: OidcUtils.encryptJson(json, configContext.getStateCookieEncryptionKey()) throws while building the state cookie in CodeAuthenticationMechanism (state cookie encryption enabled via quarkus.oidc.token-state-manager.encryption or state cookie secret).
Common situations: State cookie encryption key set to an invalid length/format for the AES algorithm; different keys across cluster nodes (one node can't decrypt, but encrypt-side misconfig also fails here); JDK without required JCE policy; key containing whitespace/encoding artifacts from env substitution.
Related errors
- Secret key for encrypting state cookie is less than 16 chara
- Authorization response 'iss' parameter '%s' does not match t
- Authorization response 'iss' parameter is required but is no
- ID Token is required to contain 'exp' and 'iat' claims
- ID token values are not equal
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/9e393cbbb7023a49.
Report an issue: GitHub.