quarkusio/quarkus · error · RuntimeException

Shared keys for persistent logins must be more than 16 chara

Error message

Shared keys for persistent logins must be more than 16 characters long

What it means

PersistentLoginManager encrypts persistent login cookies with AES. A configured encryption key shorter than 16 characters is rejected with a RuntimeException because short keys provide insufficient entropy for the SHA-256-derived AES key.

Source

Thrown at extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/PersistentLoginManager.java:59

    private final String cookiePath;
    private final long maxAgeSeconds;
    private final String cookieDomain;

    public PersistentLoginManager(String encryptionKey, String cookieName, long timeoutMillis, long newCookieIntervalMillis,
            boolean httpOnlyCookie, String cookieSameSite, String cookiePath, long maxAgeSeconds, String cookieDomain) {
        this.cookieName = cookieName;
        this.newCookieIntervalMillis = newCookieIntervalMillis;
        this.timeoutMillis = timeoutMillis;
        this.httpOnlyCookie = httpOnlyCookie;
        this.cookieSameSite = CookieSameSite.valueOf(cookieSameSite);
        this.cookiePath = cookiePath;
        this.maxAgeSeconds = maxAgeSeconds;
        this.cookieDomain = cookieDomain;
        try {
            if (encryptionKey == null) {
                this.secretKey = KeyGenerator.getInstance("AES").generateKey();
            } else if (encryptionKey.length() < 16) {
                throw new RuntimeException("Shared keys for persistent logins must be more than 16 characters long");
            } else {
                MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
                sha256.update(encryptionKey.getBytes(StandardCharsets.UTF_8));
                this.secretKey = new SecretKeySpec(sha256.digest(), "AES");
            }
        } catch (Exception t) {
            throw new RuntimeException(t);
        }
    }

    public RestoreResult restore(RoutingContext context) {
        return restore(context, cookieName);
    }

    public RestoreResult restore(RoutingContext context, String cookieName) {
        Cookie existing = context.request().getCookie(cookieName);
        // If there is no credential cookie, we have nothing to restore.
        if (existing == null) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set an encryption key of at least 16 characters (longer is better, e.g. 32+ random chars).
  2. Generate a key with openssl rand -base64 32 and place it in the config.
  3. Keep null to have a random key generated (note: not durable across restarts).

Example fix

// before
quarkus.http.auth.session.encryption-key=short
// after
quarkus.http.auth.session.encryption-key=rT7kPq2vXmN4bC8dF1gH3jL5zA9wEyU0
Defensive patterns

Strategy: validation

Validate before calling

String key = config.getValue("quarkus.http.auth.session.encryption-key", String.class);
if (key != null && key.length() < 16) {
  throw new IllegalStateException("encryption-key must be at least 16 characters");
}

Prevention

When it happens

Trigger: Setting quarkus.http.auth.session.encryption-key (or the persistent login encryption key) to a string shorter than 16 characters while form-based persistent login is enabled.

Common situations: Dev/test keys like 'secret' or 'changeme' left in configuration, or keys truncated during copy-paste/environment variable substitution.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/e1e46a476d43e5bc. Report an issue: GitHub.