@Override
  public boolean isConfiguredFor(RealmModel realm, UserModel user, String type) {
    if (!StorageId.isLocalStorage(user)) {
      String providerId = StorageId.resolveProviderId(user);
      UserStorageProvider provider =
          UserStorageManager.getStorageProvider(session, realm, providerId);
      if (provider instanceof CredentialInputValidator) {
        CredentialInputValidator validator = (CredentialInputValidator) provider;
        if (validator.supportsCredentialType(type)
            && validator.isConfiguredFor(realm, user, type)) {
          return true;
        }
      }
    } else {
      // <deprecate>
      UserFederationProvider link = session.users().getFederationLink(realm, user);
      if (link != null) {
        if (link.isConfiguredFor(realm, user, type)) return true;
      }
      // </deprecate>
      else if (user.getFederationLink() != null) {
        UserStorageProvider provider =
            UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
        if (provider != null && provider instanceof CredentialInputValidator) {
          if (((CredentialInputValidator) provider).isConfiguredFor(realm, user, type)) return true;
        }
      }
    }

    return isConfiguredLocally(realm, user, type);
  }
  @Override
  public void updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
    if (!StorageId.isLocalStorage(user)) {
      String providerId = StorageId.resolveProviderId(user);
      UserStorageProvider provider =
          UserStorageManager.getStorageProvider(session, realm, providerId);
      if (provider instanceof CredentialInputUpdater) {
        CredentialInputUpdater updater = (CredentialInputUpdater) provider;
        if (updater.supportsCredentialType(input.getType())) {
          if (updater.updateCredential(realm, user, input)) return;
        }
      }
    } else {
      // <deprecated>
      UserFederationProvider link = session.users().getFederationLink(realm, user);
      if (link != null) {
        if (link.updateCredential(realm, user, input)) return;
      }
      // </deprecated>
      else if (user.getFederationLink() != null) {
        UserStorageProvider provider =
            UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
        if (provider != null && provider instanceof CredentialInputUpdater) {
          if (((CredentialInputUpdater) provider).updateCredential(realm, user, input)) return;
        }
      }
    }

    List<CredentialInputUpdater> credentialProviders =
        getCredentialProviders(realm, CredentialInputUpdater.class);
    for (CredentialInputUpdater updater : credentialProviders) {
      if (!updater.supportsCredentialType(input.getType())) continue;
      if (updater.updateCredential(realm, user, input)) return;
    }
  }
  @Override
  public void disableCredential(RealmModel realm, UserModel user, String credentialType) {
    if (!StorageId.isLocalStorage(user)) {
      String providerId = StorageId.resolveProviderId(user);
      UserStorageProvider provider =
          UserStorageManager.getStorageProvider(session, realm, providerId);
      if (provider instanceof CredentialInputUpdater) {
        CredentialInputUpdater updater = (CredentialInputUpdater) provider;
        if (updater.supportsCredentialType(credentialType)) {
          updater.disableCredentialType(realm, user, credentialType);
        }
      }
    } else {
      UserFederationProvider link = session.users().getFederationLink(realm, user);
      if (link != null && link.getSupportedCredentialTypes().contains(credentialType)) {
        link.disableCredentialType(realm, user, credentialType);
      } else if (user.getFederationLink() != null) {
        UserStorageProvider provider =
            UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
        if (provider != null && provider instanceof CredentialInputUpdater) {
          ((CredentialInputUpdater) provider).disableCredentialType(realm, user, credentialType);
        }
      }
    }

    List<CredentialInputUpdater> credentialProviders =
        getCredentialProviders(realm, CredentialInputUpdater.class);
    for (CredentialInputUpdater updater : credentialProviders) {
      if (!updater.supportsCredentialType(credentialType)) continue;
      updater.disableCredentialType(realm, user, credentialType);
    }
  }
  @Override
  public CredentialValidationOutput authenticate(
      KeycloakSession session, RealmModel realm, CredentialInput input) {
    List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
    List<UserFederationProvider> fedProviders = new ArrayList<UserFederationProvider>();
    for (UserFederationProviderModel fedProviderModel : fedProviderModels) {
      UserFederationProvider provider = session.users().getFederationProvider(fedProviderModel);
      if (input instanceof UserCredentialModel
          && provider != null
          && provider.supportsCredentialType(input.getType())) {
        CredentialValidationOutput output =
            provider.validCredentials(realm, (UserCredentialModel) input);
        if (output != null) return output;
      }
    }

    List<CredentialAuthentication> list =
        UserStorageManager.getStorageProviders(session, realm, CredentialAuthentication.class);
    for (CredentialAuthentication auth : list) {
      if (auth.supportsCredentialAuthenticationFor(input.getType())) {
        CredentialValidationOutput output = auth.authenticate(realm, input);
        if (output != null) return output;
      }
    }

    list = getCredentialProviders(realm, CredentialAuthentication.class);
    for (CredentialAuthentication auth : list) {
      if (auth.supportsCredentialAuthenticationFor(input.getType())) {
        CredentialValidationOutput output = auth.authenticate(realm, input);
        if (output != null) return output;
      }
    }

    return null;
  }
  @Override
  public boolean isValid(RealmModel realm, UserModel user, List<CredentialInput> inputs) {

    List<CredentialInput> toValidate = new LinkedList<>();
    toValidate.addAll(inputs);
    if (!StorageId.isLocalStorage(user)) {
      String providerId = StorageId.resolveProviderId(user);
      UserStorageProvider provider =
          UserStorageManager.getStorageProvider(session, realm, providerId);
      if (provider instanceof CredentialInputValidator) {
        Iterator<CredentialInput> it = toValidate.iterator();
        while (it.hasNext()) {
          CredentialInput input = it.next();
          CredentialInputValidator validator = (CredentialInputValidator) provider;
          if (validator.supportsCredentialType(input.getType())
              && validator.isValid(realm, user, input)) {
            it.remove();
          }
        }
      }
    } else {
      // <deprecate>
      UserFederationProvider link = session.users().getFederationLink(realm, user);
      if (link != null) {
        session.users().validateUser(realm, user);
        validate(realm, user, toValidate, link);
      } // </deprecate>
      else if (user.getFederationLink() != null) {
        UserStorageProvider provider =
            UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
        if (provider != null && provider instanceof CredentialInputValidator) {
          validate(realm, user, toValidate, ((CredentialInputValidator) provider));
        }
      }
    }

    if (toValidate.isEmpty()) return true;

    List<CredentialInputValidator> credentialProviders =
        getCredentialProviders(realm, CredentialInputValidator.class);
    for (CredentialInputValidator validator : credentialProviders) {
      validate(realm, user, toValidate, validator);
    }
    return toValidate.isEmpty();
  }