justauth/JustAuth · error · AuthException

Invalid key: ${Arrays.toString(key)}

Error message

Invalid key: ${Arrays.toString(key)}

What it means

Internal guard in GlobalAuthUtils.sign: SecretKeySpec/Mac.init threw InvalidKeyException, i.e. the key bytes are unusable for the requested MAC. In practice this means the key material was null-derived or degenerate — typically an empty client-secret/agent credential reaching the signature path. The message leaks the raw key bytes via Arrays.toString(key), which itself is worth noting for log hygiene with real secrets.

Source

Thrown at src/main/java/me/zhyd/oauth/utils/GlobalAuthUtils.java:57

    }

    /**
     * 签名
     *
     * @param key       key
     * @param data      data
     * @param algorithm algorithm
     * @return byte[]
     */
    private static byte[] sign(byte[] key, byte[] data, String algorithm) {
        try {
            Mac mac = Mac.getInstance(algorithm);
            mac.init(new SecretKeySpec(key, algorithm));
            return mac.doFinal(data);
        } catch (NoSuchAlgorithmException ex) {
            throw new AuthException("Unsupported algorithm: " + algorithm, ex);
        } catch (InvalidKeyException ex) {
            throw new AuthException("Invalid key: " + Arrays.toString(key), ex);
        }
    }

    /**
     * 编码
     *
     * @param value str
     * @return encode str
     */
    public static String urlEncode(String value) {
        if (value == null) {
            return "";
        }
        try {
            String encoded = URLEncoder.encode(value, GlobalAuthUtils.DEFAULT_ENCODING.displayName());
            return encoded.replace("+", "%20").replace("*", "%2A").replace("~", "%7E").replace("/", "%2F");
        } catch (UnsupportedEncodingException e) {
            throw new AuthException("Failed To Encode Uri", e);

View on GitHub (pinned to 694bbf1b01)

Solutions

  1. Verify the secret is non-empty before calling the SDK flow that signs requests (Douyin/DingTalk style agents): log config.getClientSecret() != null && !isBlank, never the value itself.
  2. Check which credential maps to the signing key for that platform — some (e.g. agentId/clientSecret) are easily swapped.
  3. Load-test profiles: ensure the same config source is used in test and prod.
  4. If you control the code path, reject empty secrets at startup instead of letting sign() fail mid-request.

Example fix

// before
AuthConfig cfg = AuthConfig.builder().clientId(id).redirectUri(uri).build(); // secret forgotten
new AuthDingTalkRequest(cfg, cache).getAccessToken(callback);

// after
if (StringUtil.isEmpty(cfg.getClientSecret())) {
    throw new IllegalStateException("clientSecret required for this platform");
}
AuthConfig cfg = AuthConfig.builder().clientId(id).clientSecret(secret).redirectUri(uri).build();
Defensive patterns

Strategy: validation

Validate before calling

if (StringUtils.isEmpty(config.getClientSecret())) {
    throw new IllegalStateException("clientSecret is required for " + source.getName());
}

Try / catch

catch (AuthException e) { if (e.getMessage() != null && e.getMessage().startsWith("Invalid key:")) { /* credential missing/mismatched — never log the key bytes this message contains */ } }

Prevention

When it happens

Trigger: A JustAuth request class calls GlobalAuthUtils.sign (or exchangeCgtx/dingtalk-style signing) with a byte[] key built from a secret that is null or zero-length, e.g. config.getClientSecret() missing while a signature-secured endpoint is invoked. Note: a null SecretKeySpec constructor usually fails earlier with IllegalArgumentException, so the realistic path is a provider/key mismatch or empty-key edge on certain JVMs.

Common situations: AuthConfig built from env vars where the secret variable was unset; YAML indentation hiding the secret key; credentials swapped (clientId used as secret); provider config objects partially populated in tests/mocks.

Related errors


AI-assisted analysis of justauth/JustAuth@694bbf1b01 (2026-08-14). Data as JSON: /api/errors/f08784f3639b0d1c. Report an issue: GitHub.