alibaba/nacos · error · AccessException

invalid token, username is empty

Error message

invalid token, username is empty

What it means

When parsing a token that is absent from the cache, CachedJwtTokenManager decodes the JWT and reads the subject via authentication.getName(). A well-formed Nacos token always carries a non-empty username; if the subject is null or empty the token is treated as invalid/malformed and AccessException is thrown. This is an auth-denial, distinct from a signature failure (which surfaces earlier inside jwtTokenManager.getAuthentication).

Source

Thrown at plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/impl/CachedJwtTokenManager.java:168

            TimeUnit.SECONDS.toMillis(jwtTokenManager.getExpiredTimeInSeconds(token));
        if (expiredTime <= System.currentTimeMillis()) {
            return;
        }
        NacosUser user = jwtTokenManager.parseToken(token);
        tokenMap.putIfAbsent(token,
            new TokenEntity(token, username, expiredTime, authentication, user));
    }
    
    @Override
    public NacosUser parseToken(String token) throws AccessException {
        TokenEntity cached = tokenMap.get(token);
        if (cached != null) {
            return cached.getNacosUser();
        }
        Authentication authentication = jwtTokenManager.getAuthentication(token);
        String username = authentication.getName();
        if (username == null || username.isEmpty()) {
            throw new AccessException("invalid token, username is empty");
        }
        long expiredTime =
            TimeUnit.SECONDS.toMillis(jwtTokenManager.getExpiredTimeInSeconds(token));
        if (expiredTime <= System.currentTimeMillis()) {
            throw new AccessException("expired token");
        }
        NacosUser user = jwtTokenManager.parseToken(token);
        tokenMap.putIfAbsent(token,
            new TokenEntity(token, username, expiredTime, authentication, user));
        return user;
    }
    
    public long getTokenTtlInSeconds(String token) throws AccessException {
        TokenEntity cached = tokenMap.get(token);
        if (cached != null) {
            return TimeUnit.MILLISECONDS.toSeconds(
                cached.getExpiredTimeMills() - System.currentTimeMillis());
        }

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Discard the offending token and obtain a fresh one via the login API (POST /v3/auth/login).
  2. If minting tokens yourself, always set a non-empty username/sub claim using the Nacos JwtParser builder.
  3. Confirm the token was issued by a compatible Nacos version with the same secret key.
  4. Inspect the JWT payload (base64-decode the middle segment) to confirm the sub claim.

Example fix

// before: token missing sub claim
String payload = Jwts.builder().setClaims(Map.of()).compact(); // parseToken -> AccessException

// after: always include username
String token = jwtTokenManager.createToken("alice"); // sets sub=alice
Defensive patterns

Strategy: validation

Validate before calling

// Validate the JWT carries a non-empty subject before calling parseToken.
try {
    String[] parts = token.split("\\.");
    if (parts.length < 2) throw new IllegalArgumentException("not a JWT");
    String payload = new String(java.util.Base64.getUrlDecoder().decode(parts[1]));
    com.fasterxml.jackson.databind.JsonNode node =
        com.alibaba.nacos.common.utils.JacksonUtils.toObj(payload,
            com.fasterxml.jackson.databind.JsonNode.class);
    String sub = node.path("sub").asText("");
    if (sub.isEmpty()) throw new IllegalArgumentException("token has no username/sub claim");
} catch (Exception pre) {
    // token is malformed; do not call parseToken
}

Try / catch

try {
    nacosUser = tokenManager.parseToken(token);
} catch (AccessException e) {
    if (e.getMessage().contains("username is empty")) {
        // malformed token -> treat as invalid credentials
        throw new AccessException("invalid token");
    }
    throw e;
}

Prevention

When it happens

Trigger: Presenting a hand-built JWT whose 'sub' claim is missing or empty; a token minted by an older/buggy issuer that omits the username; a token whose payload was truncated or corrupted.

Common situations: Forging/testing tokens locally without the username claim; interoperating with a non-Nacos token issuer; token corruption in transit or storage.

Understand the failure class

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/ee4ae7a1b19d190b. Report an issue: GitHub.