apache/hadoop · error · FatalRpcServerException

FATAL_UNAUTHORIZED

FATAL_UNAUTHORIZED

Error message

"Authenticated user (" + user + ") doesn't match what the client claims to be (" + protocolUser + ")"

What it means

During connection-context processing, when the connection is authenticated (Kerberos or token) and the client's declared effective user differs from the authenticated user, the server treats it as proxying. Proxying is allowed for Kerberos/simple auth but forbidden for token (delegation token) authentication, so FATAL_UNAUTHORIZED with an AccessControlException is thrown. The message names both the authenticated user and the claimed (doAs) user.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java:2771

      }
      connectionContext = getMessage(IpcConnectionContextProto.getDefaultInstance(), buffer);
      protocolName = connectionContext.hasProtocol() ? connectionContext
          .getProtocol() : null;

      UserGroupInformation protocolUser = ProtoUtil.getUgi(connectionContext);
      if (authProtocol == AuthProtocol.NONE) {
        user = protocolUser;
      } else {
        // user is authenticated
        user.setAuthenticationMethod(authMethod);
        //Now we check if this is a proxy user case. If the protocol user is
        //different from the 'user', it is a proxy user scenario. However, 
        //this is not allowed if user authenticated with DIGEST.
        if ((protocolUser != null)
            && (!protocolUser.getUserName().equals(user.getUserName()))) {
          if (authMethod == AuthMethod.TOKEN) {
            // Not allowed to doAs if token authentication is used
            throw new FatalRpcServerException(
                RpcErrorCodeProto.FATAL_UNAUTHORIZED,
                new AccessControlException("Authenticated user (" + user
                    + ") doesn't match what the client claims to be ("
                    + protocolUser + ")"));
          } else {
            // Effective user can be different from authenticated user
            // for simple auth or kerberos auth
            // The user is the real user. Now we create a proxy user
            UserGroupInformation realUser = user;
            user = UserGroupInformation.createProxyUser(protocolUser
                .getUserName(), realUser);
          }
        }
      }
      authorizeConnection();
      // don't set until after authz because connection isn't established
      connectionContextRead = true;
      if (user != null) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Drop the doAs: connect as the delegation token's owner (the effective user must equal the token owner)
  2. If impersonation is required, authenticate with Kerberos as the real user and use UserGroupInformation.createProxyUser with proper hadoop.proxyuser.*.groups/hosts configuration instead of a token
  3. Check which UGI the client proxy was built from (UserGroupInformation.getCurrentUser()) before creating the RPC proxy, and rebuild the proxy from the correct UGI
  4. Audit middleware (Hive, Oozie, JDBC drivers) settings like hive.server2.proxy.user or doAs that inject an effective user on token connections

Example fix

// before: token-authenticated ugi, proxying as someone else
UserGroupInformation tokenUgi = UserGroupInformation.createRemoteUser(tokenOwner);
UserGroupInformation proxy = UserGroupInformation.createProxyUser("otheruser", tokenUgi);
proxy.doAs(action); // throws: token auth cannot doAs

// after: either use the token owner directly...
tokenUgi.doAs(action);
// ...or authenticate with Kerberos and configure proxyuser for the real user
Defensive patterns

Strategy: validation

Validate before calling

// before building the proxy on a token-authenticated UGI, assert no doAs mismatch
UserGroupInformation current = UserGroupInformation.getCurrentUser();
if (current.getAuthenticationMethod() == AuthMethod.TOKEN
    && !current.getShortUserName().equals(effectiveUser)) {
  throw new IllegalArgumentException(
      "Cannot doAs '" + effectiveUser + "' with a delegation token owned by "
      + current.getShortUserName() + "; use the token owner or Kerberos proxying");
}

Try / catch

try {
  proxy.doSomething();
} catch (RemoteException re) {
  if (re.getClassName().contains("AccessControlException")
      && re.getMessage().contains("doesn't match what the client claims")) {
    // reconnect without doAs, or re-authenticate with Kerberos for proxying
  } else { throw re; }
}

Prevention

When it happens

Trigger: A client authenticates with a delegation token whose owner is userA but sets the connection context effective user to userB (doAs); frameworks calling UserGroupInformation.createProxyUser on top of a token-authenticated UGI; Oozie/Hive-style impersonation while holding a delegation token.

Common situations: Sqoop/Oozie/Hive jobs that proxy as the job owner while the connection was authenticated with a delegation token; application servers reusing a token-authenticated UGI and then switching effective users per request; misconfigured proxyuser settings where teams reach for tokens instead of Kerberos proxying.

Understand the failure class

Related errors


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