We would like to revisit the `Authentication` class to make it provide better and easier to use interface to the consumers. 

#79809 enables run-as for all authentication schemes in addition to `realm` which is already supported. This adds more complexity to an `Authentication` object and how it should be used. For an example, building the role associated to an user now has to consider whether the user is the authenticated user or run-as user and the authentication scheme of the authenticated user. The existing `Authentication` class can answer all these question today. But its interface and internals are not aligned for these questions and the usage is error prone. For example, the `Authentication` object itself does not know whether the user has run-as. This information is kept by the `User` object. If the `User` object has an `authenticatedUser`, it's the run-as user. Otherwise it is not. But the information about realms for each `User` is directly kept in `Authentication`. Therefore, for full picture, the caller must check both `User` and `Authentication` realms and understands the nuance of their differenent combinations. 

- [x] Refactor CompositeRolesStore to separate roleDescriptors resolving (#80926)
- [ ] Move effective role descriptor checking from Resolver to CompositeRolesStore
- [x] https://github.com/elastic/elasticsearch/issues/81192
- [ ] Replace Authentication with AuthenticationContext in places other than CompositeRolesStore
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/Subject.java
}
        final String[] allRoleNames;
        if (anonymousUser == null || false == anonymousUser.enabled()) {
            allRoleNames = user.roles();
        } else {
            
            if (anonymousUser.roles().length == 0) {
                throw new IllegalStateException("anonymous is only enabled when the anonymous user has roles");
            }
            allRoleNames = ArrayUtils.concat(user.roles(), anonymousUser.roles());
        }
        return new RoleReferenceIntersection(new RoleReference.NamedRoleReference(allRoleNames));
    }
    private RoleReferenceIntersection buildRoleReferencesForApiKey() {
        if (version.before(VERSION_API_KEY_ROLES_AS_BYTES)) {
            return buildRolesReferenceForApiKeyBwc();
        }
        final String apiKeyId = (String) metadata.get(AuthenticationField.API_KEY_ID_KEY);
        final BytesReference roleDescriptorsBytes = (BytesReference) metadata.get(API_KEY_ROLE_DESCRIPTORS_KEY);
        final BytesReference limitedByRoleDescriptorsBytes = getLimitedByRoleDescriptorsBytes();
        if (roleDescriptorsBytes == null && limitedByRoleDescriptorsBytes == null) {
            throw new ElasticsearchSecurityException("no role descriptors found for API key");
        }
        final RoleReference.ApiKeyRoleReference limitedByRoleReference = new RoleReference.ApiKeyRoleReference(
            apiKeyId,
            limitedByRoleDescriptorsBytes,
            RoleReference.ApiKeyRoleType.LIMITED_BY
        );
        if (isEmptyRoleDescriptorsBytes(roleDescriptorsBytes)) {
            return new RoleReferenceIntersection(limitedByRoleReference);