/**
   * Looks up the mfa data for a specific service.
   *
   * @param targetService the service to check
   * @return service specific mfa settings
   */
  private ServiceMfaData getServicesAuthenticationData(final WebApplicationService targetService) {
    final RegisteredService registeredService = this.servicesManager.findServiceBy(targetService);
    if (registeredService == null) {
      logger.debug(
          "No registered service is found. Delegating to the next argument extractor in the chain...");
      return null;
    }

    if (!(registeredService instanceof RegisteredServiceWithAttributes)) {
      logger.debug("Registered service is not capable of defining an mfa attribute.");
      return null;
    }

    final ServiceMfaData serviceData = new ServiceMfaData();

    final RegisteredServiceWithAttributes service =
        RegisteredServiceWithAttributes.class.cast(registeredService);

    final Map mfaRole = Map.class.cast(service.getExtraAttributes().get(MFA_ROLE));
    if (mfaRole == null) {
      return null;
    }

    serviceData.setAttributeName(String.class.cast(mfaRole.get(MFA_ATTRIBUTE_NAME)));
    serviceData.setAttributePattern(String.class.cast(mfaRole.get(MFA_ATTRIBUTE_PATTERN)));
    serviceData.setAuthenticationMethod(
        String.class.cast(service.getExtraAttributes().get(AUTHN_METHOD)));

    if (serviceData.isValid()) {
      return serviceData;
    }

    return null;
  }
  /**
   * Gets mfa request context.
   *
   * @param serviceMfaData service specific mfa settings
   * @param attributeValue the value found in the attribute
   * @param targetService the target service
   * @return the mfa request context
   */
  private MultiFactorAuthenticationRequestContext getMfaRequestContext(
      final ServiceMfaData serviceMfaData,
      final String attributeValue,
      final WebApplicationService targetService) {
    final RegisteredService registeredService = this.servicesManager.findServiceBy(targetService);
    final RegisteredServiceWithAttributes service =
        RegisteredServiceWithAttributes.class.cast(registeredService);
    final String method = String.class.cast(service.getExtraAttributes().get("method"));

    if (match(serviceMfaData.getAttributePattern(), attributeValue)) {
      if (!this.authenticationMethodConfiguration.containsAuthenticationMethod(
          serviceMfaData.getAuthenticationMethod())) {
        logger.info(
            "MFA attribute [{}] with value [{}] is not supported by the authentication method configuration.",
            serviceMfaData.getAttributeName(),
            serviceMfaData.getAuthenticationMethod());
        return null;
      }
      final int mfaMethodRank =
          this.authenticationMethodConfiguration
              .getAuthenticationMethod(serviceMfaData.getAuthenticationMethod())
              .getRank();
      final MultiFactorAuthenticationSupportingWebApplicationService svc =
          this.mfaServiceFactory.create(
              targetService.getId(),
              targetService.getId(),
              targetService.getArtifactId(),
              "POST".equals(method) ? ResponseType.POST : ResponseType.REDIRECT,
              serviceMfaData.getAuthenticationMethod(),
              MultiFactorAuthenticationSupportingWebApplicationService.AuthenticationMethodSource
                  .PRINCIPAL_ATTRIBUTE);

      return new MultiFactorAuthenticationRequestContext(svc, mfaMethodRank);
    }

    logger.trace("{} did not match {}", attributeValue, serviceMfaData.getAttributePattern());
    return null;
  }