apache/hadoop · error · IOException

Delegation Token can be issued only with kerberos or web aut

Error message

Delegation Token can be issued only with kerberos or web authentication

What it means

RouterSecurityManager.getDelegationToken refuses to issue a delegation token when isAllowedDelegationTokenOp() returns false: security is enabled (UserGroupInformation.isSecurityEnabled()) but the connection's authentication method is not KERBEROS, KERBEROS_SSL, or CERTIFICATE. getConnectionAuthenticationMethod() unwraps PROXY to inspect the real user's method. Despite the message wording ('kerberos or web authentication'), the code only accepts the strong auth methods — the point is that a weakly-authenticated (e.g. SIMPLE or DIGEST/token-authenticated) connection may not mint new tokens.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/security/RouterSecurityManager.java:133

    }
    return true;
  }

  /**
   * @param renewer Renewer information
   * @return delegation token
   * @throws IOException on error
   */
  public Token<DelegationTokenIdentifier> getDelegationToken(Text renewer)
      throws IOException {
    LOG.debug("Generate delegation token with renewer " + renewer);
    final String operationName = "getDelegationToken";
    boolean success = false;
    String tokenId = "";
    Token<DelegationTokenIdentifier> token;
    try {
      if (!isAllowedDelegationTokenOp()) {
        throw new IOException(
            "Delegation Token can be issued only " +
                "with kerberos or web authentication");
      }
      if (dtSecretManager == null || !dtSecretManager.isRunning()) {
        LOG.warn("trying to get DT with no secret manager running");
        return null;
      }
      UserGroupInformation ugi = getRemoteUser();
      String user = ugi.getUserName();
      Text owner = new Text(user);
      Text realUser = null;
      if (ugi.getRealUser() != null) {
        realUser = new Text(ugi.getRealUser().getUserName());
      }
      DelegationTokenIdentifier dtId = new DelegationTokenIdentifier(owner,
          renewer, realUser);
      token = new Token<DelegationTokenIdentifier>(
          dtId, dtSecretManager);

View on GitHub (pinned to 2add963021)

Solutions

  1. Authenticate with kerberos before requesting the token: kinit, or UserGroupInformation.loginUserFromKeytab, so the RPC connection carries KERBEROS authentication.
  2. Never call getDelegationToken on a session already authenticated by a delegation token — fetch the token once via kerberos, then renew/cancel it as needed.
  3. If using a proxy user, make sure the real (underlying) user authenticated with kerberos, not SIMPLE.
  4. Align hadoop.security.authentication=kerberos in the client's core-site.xml with the secured Router.

Example fix

// before: SIMPLE-authenticated UGI on a secured cluster
FileSystem fs = FileSystem.get(conf);
Token<?> t = fs.getDelegationToken("yarn"); // throws

// after: kerberos login first, then fetch
UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab("hdfs/_HOST@REALM", "/etc/security/keytabs/hdfs.keytab");
FileSystem fs = UserGroupInformation.getLoginUser().doAs((PrivilegedExceptionAction<FileSystem>) () -> FileSystem.get(conf));
Token<?> t = fs.getDelegationToken("yarn");
Defensive patterns

Strategy: validation

Validate before calling

// Check the connection's auth method BEFORE requesting a token
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
UserGroupInformation.AuthenticationMethod auth = ugi.getAuthenticationMethod();
if (auth == UserGroupInformation.AuthenticationMethod.PROXY && ugi.getRealUser() != null) {
  auth = ugi.getRealUser().getAuthenticationMethod();
}
if (UserGroupInformation.isSecurityEnabled()
    && auth != UserGroupInformation.AuthenticationMethod.KERBEROS) {
  throw new IllegalStateException(
      "getDelegationToken requires kerberos; current auth=" + auth);
}

Try / catch

try {
  return fs.getDelegationToken(renewer);
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().contains(
      "Delegation Token can be issued only")) {
    throw new SecurityException("Re-authenticate with kerberos (kinit) before fetching a delegation token", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling getDelegationToken on a secured cluster without a kerberos-authenticated connection: client never did kinit/loginUserFromKeytab; the client authenticated with an existing delegation token (DIGEST) and tries to mint another token from it; a proxy user whose real user is SIMPLE-authenticated; client-side config says simple while the Router requires kerberos.

Common situations: Oozie/Spark/Hive workflow that fetchs a DT from a non-kerberos context; developer testing against a secured router with an unauthenticated FileSystem; tooling that connects via WebHDFS without SPNEGO; proxy-user setups where the real user lost kerberos.

Understand the failure class

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/1ac6adbfef546898. Report an issue: GitHub.