private void refreshEntry(Context context, CacheEntry entry)
     throws IOException, MessagingException {
   LogUtils.d(Logging.LOG_TAG, "AuthenticationCache refreshEntry %d", entry.mAccountId);
   try {
     final AuthenticationResult result =
         mAuthenticator.requestRefresh(context, entry.mProviderId, entry.mRefreshToken);
     // Don't set the refresh token here, it's not returned by the refresh response,
     // so setting it here would make it blank.
     entry.mAccessToken = result.mAccessToken;
     entry.mExpirationTime =
         result.mExpiresInSeconds * DateUtils.SECOND_IN_MILLIS + System.currentTimeMillis();
     saveEntry(context, entry);
   } catch (AuthenticationFailedException e) {
     // This is fatal. Clear the tokens and rethrow the exception.
     LogUtils.d(Logging.LOG_TAG, "authentication failed, clearning");
     clearEntry(context, entry);
     throw e;
   } catch (MessagingException e) {
     LogUtils.d(Logging.LOG_TAG, "messaging exception");
     throw e;
   } catch (IOException e) {
     LogUtils.d(Logging.LOG_TAG, "IO exception");
     throw e;
   }
 }
  @Override
  public String getAuthorizationHeader(
      @NotNull final String oauthProviderName,
      @NotNull final String userId,
      @NotNull final String requestMethod,
      @NotNull final String requestUrl,
      @NotNull final Map<String, String> requestParameters)
      throws IOException {

    final OAuthAuthenticator oAuthAuthenticator =
        oAuthAuthenticatorProvider.getAuthenticator(oauthProviderName);
    if (oAuthAuthenticator != null) {
      return oAuthAuthenticator.computeAuthorizationHeader(
          userId, requestMethod, requestUrl, requestParameters);
    }
    return null;
  }
  @Override
  public AuthenticationMechanismOutcome authenticate(
      HttpServerExchange exchange, SecurityContext securityContext) {
    BearerTokenAuthenticator bearer = createBearerTokenAuthenticator();
    AuthenticationMechanismOutcome outcome = bearer.authenticate(exchange);
    if (outcome == AuthenticationMechanismOutcome.NOT_AUTHENTICATED) {
      exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, bearer.getChallenge());
      return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
    } else if (outcome == AuthenticationMechanismOutcome.AUTHENTICATED) {
      final SkeletonKeyToken token = bearer.getToken();
      String surrogate = bearer.getSurrogate();
      SkeletonKeySession session =
          new SkeletonKeySession(bearer.getTokenString(), token, resourceMetadata);
      propagateBearer(exchange, session);
      completeAuthentication(exchange, securityContext, token, surrogate);
      return AuthenticationMechanismOutcome.AUTHENTICATED;
    } else if (config.isBearerOnly()) {
      exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, bearer.getChallenge());
      return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
    }

    OAuthAuthenticator oauth = createOAuthAuthenticator(exchange);
    outcome = oauth.authenticate();
    if (outcome == AuthenticationMechanismOutcome.NOT_AUTHENTICATED) {
      exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, oauth.getChallenge());
      return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
    } else if (outcome == AuthenticationMechanismOutcome.NOT_ATTEMPTED) {
      exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, oauth.getChallenge());
      return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
    }
    SkeletonKeySession session =
        new SkeletonKeySession(oauth.getTokenString(), oauth.getToken(), resourceMetadata);
    propagateOauth(exchange, session);
    completeAuthentication(exchange, securityContext, oauth.getToken(), null);
    log.info("AUTHENTICATED");
    return AuthenticationMechanismOutcome.AUTHENTICATED;
  }
  private void doProcess(final HttpServletRequest request, final HttpResponse response)
      throws OAuthSystemException, IOException {
    OAuthResponse oauthResponse;
    String state = request.getParameter(OAuth.OAUTH_STATE);
    String redirectUri = request.getParameter(OAuth.OAUTH_REDIRECT_URI);
    try {
      // Build a request and fail if it is not a valid OAUTH request
      final OAuthAuthzRequest oAuthAuthzRequest = new OAuthAuthzRequest(request);

      // Get oauth parameters
      final String clientId = oAuthAuthzRequest.getClientId();
      final String responseType = oAuthAuthzRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);
      final Set<String> scopes = oAuthAuthzRequest.getScopes();
      redirectUri = oAuthAuthzRequest.getRedirectURI();
      state = oAuthAuthzRequest.getState();

      int expiresIn = DEFAULT_EXPIRE_TIME;
      if (scopes.contains("permanent_token")) {
        expiresIn = DateUtils.SECOND_PER_DAY * 3650;
      }

      if (redirectUri == null || redirectUri.isEmpty()) {
        redirectUri = "pagenotfound";
      }

      final String login = request.getParameter("login");
      final String password = request.getParameter("password");

      final OAuthASResponse.OAuthAuthorizationResponseBuilder builder =
          OAuthASResponse.authorizationResponse(HttpServletResponse.SC_FOUND);

      // TODO make a more secure Generator ?
      final OAuthIssuer oauthIssuerImpl = new OAuthIssuerImpl(new UUIDValueGenerator());

      if (responseType.equals(ResponseType.CODE.toString())) {
        // Create the token
        final String token = oauthIssuerImpl.authorizationCode();
        // build response
        builder.setCode(token);
        // Add the external service
        authenticator.addExternalService(clientId, login, password, token, scopes);

      } else if (responseType.equals(ResponseType.TOKEN.toString())) {
        // Create tokens
        final String token = oauthIssuerImpl.accessToken();
        final String refresh = oauthIssuerImpl.refreshToken();
        // build response
        builder.setAccessToken(token);
        builder.setParam(OAuth.OAUTH_REFRESH_TOKEN, refresh);
        builder.setExpiresIn(String.valueOf(expiresIn));
        // Add in external services
        authenticator.addExternalService(clientId, login, password, token, scopes);
        authenticator.authorize(token, token, refresh, expiresIn);
      }

      // Finish the construction
      oauthResponse = builder.location(redirectUri).buildQueryMessage();

    } catch (final OAuthProblemException ex) {
      oauthResponse =
          OAuthResponse.errorResponse(HttpServletResponse.SC_FOUND)
              .error(ex)
              .setState(state)
              .location(redirectUri)
              .buildQueryMessage();

    } catch (final AuthorizationException e) {
      oauthResponse =
          OAuthResponse.errorResponse(HttpServletResponse.SC_FOUND)
              .setError("server_error")
              .setErrorDescription("Internal error. Please report.")
              .setState(state)
              .location(redirectUri)
              .buildQueryMessage();

      Log.framework().error("Cannot found a just added service ...", e);
    } catch (final ElementNotFoundException e) {
      response.writeOAuthRedirect(
          302,
          "/"
              + OAuthProcessor.OAUTH_GET_CREDENTIAL_PAGENAME
              + "?fail=true&"
              + request.getQueryString());
      return;
    } catch (final OAuthSystemException e) {
      throw new BadProgrammerException(e);
    }

    // write the response
    response.writeOAuthRedirect(oauthResponse.getResponseStatus(), oauthResponse.getLocationUri());
  }