{"record":{"id":"cfdfeda105943e27","repo":"apache/hadoop","slug":"can-t-retrieve-username-from-tokenidentifier","errorCode":null,"errorMessage":"Can't retrieve username from tokenIdentifier.","messagePattern":"Can't retrieve username from tokenIdentifier\\.","errorType":"exception","errorClass":"AccessControlException","httpStatus":null,"severity":"critical","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java","lineNumber":2235,"sourceCode":"    \n    /* Decrement the outstanding RPC count */\n    private void decRpcCount() {\n      rpcCount.decrementAndGet();\n    }\n    \n    /* Increment the outstanding RPC count */\n    private void incRpcCount() {\n      rpcCount.incrementAndGet();\n    }\n    \n    private UserGroupInformation getAuthorizedUgi(String authorizedId)\n        throws InvalidToken, AccessControlException {\n      if (authMethod == AuthMethod.TOKEN) {\n        TokenIdentifier tokenId = SaslRpcServer.getIdentifier(authorizedId,\n            secretManager);\n        UserGroupInformation ugi = tokenId.getUser();\n        if (ugi == null) {\n          throw new AccessControlException(\n              \"Can't retrieve username from tokenIdentifier.\");\n        }\n        ugi.addTokenIdentifier(tokenId);\n        return ugi;\n      } else {\n        return UserGroupInformation.createRemoteUser(authorizedId, authMethod);\n      }\n    }\n\n    private void saslReadAndProcess(RpcWritable.Buffer buffer) throws\n        RpcServerException, IOException, InterruptedException {\n      final RpcSaslProto saslMessage =\n          getMessage(RpcSaslProto.getDefaultInstance(), buffer);\n      switch (saslMessage.getState()) {\n        case WRAP: {\n          if (!saslContextEstablished || !useWrap) {\n            throw new FatalRpcServerException(\n                RpcErrorCodeProto.FATAL_INVALID_RPC_HEADER,","sourceCodeStart":2217,"sourceCodeEnd":2253,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java#L2217-L2253","documentation":"On a TOKEN-authenticated connection, getAuthorizedUgi resolves the SASL identity through SaslRpcServer.getIdentifier to a TokenIdentifier and asks it for its UserGroupInformation; if tokenId.getUser() returns null, authorization fails with AccessControlException(\"Can't retrieve username from tokenIdentifier.\"). The token parsed, but its identifier could not name an owning user — a server-side auth failure that kills the connection.","triggerScenarios":"A delegation token whose TokenIdentifier.getUser() returns null: custom TokenIdentifier implementations that never return a user, token kinds mapped to an identifier class without owner information, or tokens minted by a mismatched/older service version so the identifier decodes without an owner.","commonSituations":"Custom authentication plugins introducing new token kinds; tokens carried across service versions; proxy-user setups where the identifier lost the owner field; WebHDFS/HTTP flows surfacing this as a 401/connection failure.","solutions":["If you own the TokenIdentifier class, implement getUser() to return the owning UserGroupInformation — never null.","Verify the token's kind maps to the intended identifier class in SaslRpcServer's token identifier registry so it decodes with full owner info.","As a client, obtain a fresh delegation token from the target service — the old one decodes to an identifier without a user."],"exampleFix":"// before\npublic class MyTokenIdentifier extends AbstractDelegationTokenIdentifier {\n  @Override\n  public UserGroupInformation getUser() {\n    return null; // triggers AccessControlException on the server\n  }\n}\n// after\n@Override\npublic UserGroupInformation getUser() {\n  return UserGroupInformation.createRemoteUser(getOwner().toString());\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"Catch AccessControlException on the RPC/connection layer, treat it as a non-retryable authentication failure, and re-authenticate: fetch a fresh delegation token from the target service (or re-login for Kerberos) before reconnecting.","preventionTips":["Custom TokenIdentifier implementations must always return a UGI from getUser().","Register every token kind with its proper identifier class.","Do not carry delegation tokens across service versions; mint them from the target service."],"tags":["rpc","security","delegation-token","authentication","sasl"],"backgroundTag":"delegation-token-invalid","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}