{"record":{"id":"1ac6adbfef546898","repo":"apache/hadoop","slug":"delegation-token-can-be-issued-only-with-kerberos-1ac6ad","errorCode":null,"errorMessage":"Delegation Token can be issued only with kerberos or web authentication","messagePattern":"Delegation Token can be issued only with kerberos or web authentication","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/security/RouterSecurityManager.java","lineNumber":133,"sourceCode":"    }\n    return true;\n  }\n\n  /**\n   * @param renewer Renewer information\n   * @return delegation token\n   * @throws IOException on error\n   */\n  public Token<DelegationTokenIdentifier> getDelegationToken(Text renewer)\n      throws IOException {\n    LOG.debug(\"Generate delegation token with renewer \" + renewer);\n    final String operationName = \"getDelegationToken\";\n    boolean success = false;\n    String tokenId = \"\";\n    Token<DelegationTokenIdentifier> token;\n    try {\n      if (!isAllowedDelegationTokenOp()) {\n        throw new IOException(\n            \"Delegation Token can be issued only \" +\n                \"with kerberos or web authentication\");\n      }\n      if (dtSecretManager == null || !dtSecretManager.isRunning()) {\n        LOG.warn(\"trying to get DT with no secret manager running\");\n        return null;\n      }\n      UserGroupInformation ugi = getRemoteUser();\n      String user = ugi.getUserName();\n      Text owner = new Text(user);\n      Text realUser = null;\n      if (ugi.getRealUser() != null) {\n        realUser = new Text(ugi.getRealUser().getUserName());\n      }\n      DelegationTokenIdentifier dtId = new DelegationTokenIdentifier(owner,\n          renewer, realUser);\n      token = new Token<DelegationTokenIdentifier>(\n          dtId, dtSecretManager);","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/security/RouterSecurityManager.java#L115-L151","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Authenticate with kerberos before requesting the token: kinit, or UserGroupInformation.loginUserFromKeytab, so the RPC connection carries KERBEROS authentication.","Never call getDelegationToken on a session already authenticated by a delegation token — fetch the token once via kerberos, then renew/cancel it as needed.","If using a proxy user, make sure the real (underlying) user authenticated with kerberos, not SIMPLE.","Align hadoop.security.authentication=kerberos in the client's core-site.xml with the secured Router."],"exampleFix":"// before: SIMPLE-authenticated UGI on a secured cluster\nFileSystem fs = FileSystem.get(conf);\nToken<?> t = fs.getDelegationToken(\"yarn\"); // throws\n\n// after: kerberos login first, then fetch\nUserGroupInformation.setConfiguration(conf);\nUserGroupInformation.loginUserFromKeytab(\"hdfs/_HOST@REALM\", \"/etc/security/keytabs/hdfs.keytab\");\nFileSystem fs = UserGroupInformation.getLoginUser().doAs((PrivilegedExceptionAction<FileSystem>) () -> FileSystem.get(conf));\nToken<?> t = fs.getDelegationToken(\"yarn\");","handlingStrategy":"validation","validationCode":"// Check the connection's auth method BEFORE requesting a token\nUserGroupInformation ugi = UserGroupInformation.getCurrentUser();\nUserGroupInformation.AuthenticationMethod auth = ugi.getAuthenticationMethod();\nif (auth == UserGroupInformation.AuthenticationMethod.PROXY && ugi.getRealUser() != null) {\n  auth = ugi.getRealUser().getAuthenticationMethod();\n}\nif (UserGroupInformation.isSecurityEnabled()\n    && auth != UserGroupInformation.AuthenticationMethod.KERBEROS) {\n  throw new IllegalStateException(\n      \"getDelegationToken requires kerberos; current auth=\" + auth);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return fs.getDelegationToken(renewer);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\n      \"Delegation Token can be issued only\")) {\n    throw new SecurityException(\"Re-authenticate with kerberos (kinit) before fetching a delegation token\", e);\n  }\n  throw e;\n}","preventionTips":["Always kinit / loginUserFromKeytab in the entrypoint that fetches DTs; make it a startup assertion.","Never chain token-from-token: cache the first kerberos-fetched DT for the job instead of re-fetching from a DIGEST session.","Add a pre-flight auth check (as above) in job launchers so the failure is actionable rather than deep in HDFS."],"tags":["hdfs","router-based-federation","security","delegation-token","kerberos","authentication"],"backgroundTag":"kerberos-authentication-required","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}