private void doAuth(
      HttpServletRequest req, HttpServletResponse rsp, Deque<AuthenticationProfile> stack)
      throws IOException, ServletException {

    boolean stop = false;
    while (!stop && !stack.isEmpty()) {
      AuthenticationProfile profile = stack.peek();

      ExtMap output =
          profile
              .getAuthn()
              .invoke(
                  new ExtMap()
                      .mput(Base.InvokeKeys.COMMAND, Authn.InvokeCommands.AUTHENTICATE_NEGOTIATE)
                      .mput(Authn.InvokeKeys.HTTP_SERVLET_REQUEST, req)
                      .mput(Authn.InvokeKeys.HTTP_SERVLET_RESPONSE, rsp));

      switch (output.<Integer>get(Authn.InvokeKeys.RESULT)) {
        case Authn.AuthResult.SUCCESS:
          req.setAttribute(
              FiltersHelper.Constants.REQUEST_AUTH_RECORD_KEY,
              output.<ExtMap>get(Authn.InvokeKeys.AUTH_RECORD));
          req.setAttribute(FiltersHelper.Constants.REQUEST_AUTH_TYPE_KEY, AuthType.NEGOTIATION);
          req.setAttribute(FiltersHelper.Constants.REQUEST_PROFILE_KEY, profile.getName());
          stack.clear();
          break;

        case Authn.AuthResult.NEGOTIATION_UNAUTHORIZED:
          stack.pop();
          break;

        case Authn.AuthResult.NEGOTIATION_INCOMPLETE:
          stop = true;
          break;

        default:
          log.error(
              "Unexpected authentication result. AuthResult code is {}",
              output.<Integer>get(Authn.InvokeKeys.RESULT));
          stack.pop();
          break;
      }
    }
  }
  private synchronized void cacheNegotiatingProfiles() {
    schemes = new ArrayList<>();
    profiles = new ArrayList<>();

    for (AuthenticationProfile profile :
        AuthenticationProfileRepository.getInstance().getProfiles()) {
      ExtMap authnContext = profile.getAuthn().getContext();
      if ((authnContext.<Long>get(Authn.ContextKeys.CAPABILITIES).longValue() & caps) != 0) {
        profiles.add(profile);
        schemes.addAll(
            authnContext.<Collection<String>>get(
                Authn.ContextKeys.HTTP_AUTHENTICATION_SCHEME, Collections.<String>emptyList()));
      }
    }

    Collections.sort(
        profiles,
        new Comparator<AuthenticationProfile>() {
          @Override
          public int compare(AuthenticationProfile o1, AuthenticationProfile o2) {
            return Integer.compare(o1.getNegotiationPriority(), o2.getNegotiationPriority());
          }
        });
  }