public Result callback() {

    final PlayWebContext context = new PlayWebContext(ctx(), config.getSessionStore());

    CommonHelper.assertNotNull("config", config);
    CommonHelper.assertNotNull("config.httpActionAdapter", config.getHttpActionAdapter());
    final Clients clients = config.getClients();
    CommonHelper.assertNotNull("clients", clients);
    final Client client = clients.findClient(context);
    logger.debug("client: {}", client);
    CommonHelper.assertNotNull("client", client);
    CommonHelper.assertTrue(
        client instanceof IndirectClient, "only indirect clients are allowed on the callback url");

    final Credentials credentials;
    try {
      credentials = client.getCredentials(context);
    } catch (final RequiresHttpAction e) {
      return (Result) config.getHttpActionAdapter().adapt(e.getCode(), context);
    }
    logger.debug("credentials: {}", credentials);

    final UserProfile profile = client.getUserProfile(credentials, context);
    logger.debug("profile: {}", profile);
    saveUserProfile(context, profile);
    return redirectToOriginallyRequestedUrl(context);
  }
  @Override
  public R perform(
      final C context,
      final Config config,
      final HttpActionAdapter<R, C> httpActionAdapter,
      final String inputDefaultUrl,
      final Boolean inputMultiProfile,
      final Boolean inputRenewSession) {

    logger.debug("=== CALLBACK ===");

    // default values
    final String defaultUrl;
    if (inputDefaultUrl == null) {
      defaultUrl = Pac4jConstants.DEFAULT_URL_VALUE;
    } else {
      defaultUrl = inputDefaultUrl;
    }
    final boolean multiProfile;
    if (inputMultiProfile == null) {
      multiProfile = false;
    } else {
      multiProfile = inputMultiProfile;
    }
    final boolean renewSession;
    if (inputRenewSession == null) {
      renewSession = true;
    } else {
      renewSession = inputRenewSession;
    }

    // checks
    assertNotNull("context", context);
    assertNotNull("config", config);
    assertNotNull("httpActionAdapter", httpActionAdapter);
    assertNotBlank(Pac4jConstants.DEFAULT_URL, defaultUrl);
    final Clients clients = config.getClients();
    assertNotNull("clients", clients);

    // logic
    final Client client = clients.findClient(context);
    logger.debug("client: {}", client);
    assertNotNull("client", client);
    assertTrue(
        client instanceof IndirectClient, "only indirect clients are allowed on the callback url");

    HttpAction action;
    try {
      final Credentials credentials = client.getCredentials(context);
      logger.debug("credentials: {}", credentials);

      final CommonProfile profile = client.getUserProfile(credentials, context);
      logger.debug("profile: {}", profile);
      saveUserProfile(context, profile, multiProfile, renewSession);
      action = redirectToOriginallyRequestedUrl(context, defaultUrl);

    } catch (final HttpAction e) {
      logger.debug("extra HTTP action required in callback: {}", e.getCode());
      action = e;
    }

    return httpActionAdapter.adapt(action.getCode(), context);
  }