protected void backchannelLogout(UserSessionModel userSession, String idToken) {
   String sessionId = userSession.getId();
   UriBuilder logoutUri =
       UriBuilder.fromUri(getConfig().getLogoutUrl()).queryParam("state", sessionId);
   logoutUri.queryParam("id_token_hint", idToken);
   String url = logoutUri.build().toString();
   try {
     int status = JsonSimpleHttp.doGet(url).asStatus();
     boolean success = status >= 200 && status < 400;
     if (!success) {
       logger.warn("Failed backchannel broker logout to: " + url);
     }
   } catch (Exception e) {
     logger.warn("Failed backchannel broker logout to: " + url, e);
   }
 }
  @Override
  protected BrokeredIdentityContext getFederatedIdentity(String response) {
    AccessTokenResponse tokenResponse = null;
    try {
      tokenResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
    } catch (IOException e) {
      throw new IdentityBrokerException("Could not decode access token response.", e);
    }
    PublicKey key = getExternalIdpKey();
    String accessToken = verifyAccessToken(key, tokenResponse);

    String encodedIdToken = tokenResponse.getIdToken();

    JsonWebToken idToken = validateToken(key, encodedIdToken);

    try {
      String id = idToken.getSubject();
      BrokeredIdentityContext identity = new BrokeredIdentityContext(id);
      String name = (String) idToken.getOtherClaims().get(IDToken.NAME);
      String preferredUsername = (String) idToken.getOtherClaims().get(IDToken.PREFERRED_USERNAME);
      String email = (String) idToken.getOtherClaims().get(IDToken.EMAIL);

      if (getConfig().getUserInfoUrl() != null
          && (id == null || name == null || preferredUsername == null || email == null)) {
        SimpleHttp request =
            JsonSimpleHttp.doGet(getConfig().getUserInfoUrl())
                .header("Authorization", "Bearer " + accessToken);
        JsonNode userInfo = JsonSimpleHttp.asJson(request);

        id = getJsonProperty(userInfo, "sub");
        name = getJsonProperty(userInfo, "name");
        preferredUsername = getJsonProperty(userInfo, "preferred_username");
        email = getJsonProperty(userInfo, "email");
        AbstractJsonUserAttributeMapper.storeUserProfileForMapper(
            identity, userInfo, getConfig().getAlias());
      }
      identity.getContextData().put(FEDERATED_ACCESS_TOKEN_RESPONSE, tokenResponse);
      identity.getContextData().put(VALIDATED_ID_TOKEN, idToken);
      processAccessTokenResponse(identity, key, tokenResponse);

      identity.setId(id);
      identity.setName(name);
      identity.setEmail(email);

      identity.setBrokerUserId(getConfig().getAlias() + "." + id);
      if (tokenResponse.getSessionState() != null) {
        identity.setBrokerSessionId(getConfig().getAlias() + "." + tokenResponse.getSessionState());
      }

      if (preferredUsername == null) {
        preferredUsername = email;
      }

      if (preferredUsername == null) {
        preferredUsername = id;
      }

      identity.setUsername(preferredUsername);

      if (getConfig().isStoreToken()) {
        identity.setToken(response);
      }

      return identity;
    } catch (Exception e) {
      throw new IdentityBrokerException("Could not fetch attributes from userinfo endpoint.", e);
    }
  }