### CI Link

https://gradle-enterprise.elastic.co/s/bhuomrfypovuq

### Repro line

gradlew :x-pack:plugin:security:test --tests "org.elasticsearch.xpack.security.authc.TokenServiceTests.testInvalidateRefreshTokenThatIsAlreadyInvalidated" -Dtests.seed=819240371E8B1C23 -Dtests.locale=ms-MY -Dtests.timezone=Australia/Lindeman -Druntime.java=17

### Does it reproduce?

Yes

### Applicable branches

main

### Failure history

_No response_

### Failure excerpt

```
  2> REPRODUCE WITH: ./gradlew ':x-pack:plugin:security:test' --tests "org.elasticsearch.xpack.security.authc.TokenServiceTests.testInvalidateRefreshTokenThatIsAlreadyInvalidated" -Dtests.seed=819240371E8B1C23 -Dtests.locale=ms-MY -Dtests.timezone=Australia/Lindeman -Druntime.java=17
  2> java.lang.ClassCastException: class java.util.HashMap cannot be cast to class org.elasticsearch.common.bytes.BytesReference (java.util.HashMap is in module java.base of loader 'bootstrap'; org.elasticsearch.common.bytes.BytesReference is in unnamed module of loader 'app')
        at __randomizedtesting.SeedInfo.seed([819240371E8B1C23:50D848AB4705CC]:0)
        at org.elasticsearch.xpack.core.security.authc.Authentication.maybeRewriteMetadataForApiKeyRoleDescriptors(Authentication.java:1093)
        at org.elasticsearch.xpack.core.security.authc.Authentication.maybeRewriteMetadata(Authentication.java:271)
        at org.elasticsearch.xpack.core.security.authc.Authentication.maybeRewriteForOlderVersion(Authentication.java:232)
        at org.elasticsearch.xpack.security.authc.TokenServiceTests.buildUserToken(TokenServiceTests.java:941)
        at org.elasticsearch.xpack.security.authc.TokenServiceTests.testInvalidateRefreshTokenThatIsAlreadyInvalidated(TokenServiceTests.java:437)
```
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/Authentication.java
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.REMOTE_ACCESS_AUTHENTICATION_KEY;
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.REMOTE_ACCESS_REALM_NAME;
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.REMOTE_ACCESS_REALM_TYPE;
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.REMOTE_ACCESS_ROLE_DESCRIPTORS_KEY;
import static org.elasticsearch.xpack.core.security.authc.RealmDomain.REALM_DOMAIN_PARSER;
/**
 * The Authentication class encapsulates identity information created after successful authentication
 * and is the starting point of subsequent authorization.
 *
 * Authentication is serialized and travels across the cluster nodes as the sub-requests are handled,
 * and can also be cached by long-running jobs that continue to act on behalf of the user, beyond
 * the lifetime of the original request.
 *
 * The authentication consists of two {@link Subject}s
 * <ul>
 *     <li>{@link #authenticatingSubject} performs the authentication, i.e. it provides a credential.</li>
 *     <li>{@link #effectiveSubject} The subject that {@link #authenticatingSubject} impersonates ({@link #isRunAs()})</li>
 * </ul>
 * If {@link #isRunAs()} is {@code false}, the two {@link Subject}s will be the same object.
 *
 * Authentication also has a {@link #type} that indicates which mechanism the {@link #authenticatingSubject}
 * uses to perform the authentication.
 *
 * The Authentication's version is its {@link Subject}'s version, i.e. {@code getEffectiveSubject().getTransportVersion()}.
 * It is guaranteed that the versions are identical for the two Subjects. Hence {@code getAuthenticatingSubject().getTransportVersion()}
 * will give out the same result. But using {@code getEffectiveSubject()} is more idiomatic since most callers
 * of this class should just need to know about the {@link #effectiveSubject}. That is, often times, the caller
 * begins with {@code authentication.getEffectiveSubject()} for interrogating an Authentication object.
 */
public final class Authentication implements ToXContentObject {