Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Improve token exchange handling when token expires #6489

Merged
merged 1 commit into from
Jan 17, 2023

Conversation

nastra
Copy link
Contributor

@nastra nastra commented Dec 23, 2022

No description provided.

@github-actions github-actions bot added the core label Dec 23, 2022
import org.apache.iceberg.util.JsonUtil;
import org.immutables.value.Value;

@Value.Immutable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that @Immutable is being overused for cases like this. This class isn't complex and using it forces a lot of logic to go into default methods and the of static method. While it is useful in some cases, I think that there should be a significant savings from using immutables; we should not use them by default.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be rewritten to remove @Immutable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand your argument about potentially over-using @Immutable. However, I think there's rarely a case where the non-@Immutable version is better than the @Immutable one. In fact I initially put the JWT parsing code first into a method, then extracted it into a non-@Immutable class like the one below and eventually made it @Immutable.
The non-immutable version of that class will be longer due to boiler-plate code. Technically the constructor might even have a precondition null check for the token (which we don't need in this particular example, because we already know the token is non-null from the static method). In the @Immutable we get this stuff for free because the API definition is explicit (aka the token isn't marked as optional or nullable and therefore must always be non-null).

public class NonImmutableJwt {

  private final String token;
  private final long expiresAtEpochMillis;

  private Jwt(String token, long expiresAtEpochMillis) {
    this.token = token;
    this.expiresAtEpochMillis = expiresAtEpochMillis;
  }

  public String token() {
    return token;
  }

  public long expiresAtEpochMillis() {
    return expiresAtEpochMillis;
  }

  public long expiresInMillis() {
    return expiresAtEpochMillis() - Instant.now().toEpochMilli();
  }

  public boolean isExpired() {
    return expiresAtEpochMillis() <= Instant.now().toEpochMilli();
  }

  static Optional<Jwt> of(String token) {
    try {
      Preconditions.checkArgument(null != token, "Invalid JWT: null");
      String[] parts = token.split("\\.");
      Preconditions.checkArgument(parts.length == 3, "Invalid JWT: %s", token);

      // Parse the payload JSON
      JsonNode jsonNode = JsonUtil.mapper().readTree(Base64.getUrlDecoder().decode(parts[1]));
      Long expiresAt = JsonUtil.getLongOrNull("exp", jsonNode);
      return Optional.of(
          new Jwt(
              token,
              null == expiresAt
                  ? Long.MAX_VALUE
                  : Instant.ofEpochSecond(expiresAt).toEpochMilli()));
    } catch (Exception e) {
      return Optional.empty();
    }
  }
}

If you're strong on this one, then I can change this to a non-@Immutable version but as I've tried to outline above, I don't think there's any advantage in doing so.

Copy link

@PraveenNanda124 PraveenNanda124 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@nastra nastra force-pushed the rest-catalog-token-refresh branch 3 times, most recently from 3f01ed8 to bad42c1 Compare January 9, 2023 10:29
@nastra nastra requested a review from rdblue January 9, 2023 10:29
@nastra nastra closed this Jan 10, 2023
@nastra nastra reopened this Jan 10, 2023
@rdblue
Copy link
Contributor

rdblue commented Jan 17, 2023

@nastra, I opened a PR against your branch with the remaining changes I think we should make. Please take a look: nastra#72

Co-authored-by: Ryan Blue <blue@apache.org>
@nastra nastra requested a review from rdblue January 17, 2023 09:58
@nastra
Copy link
Contributor Author

nastra commented Jan 17, 2023

@nastra, I opened a PR against your branch with the remaining changes I think we should make. Please take a look: nastra#72

Thanks @rdblue I've applied your changes and cleaned up some tiny bits to make CI pass. I've also made sure that the changes here are compatible for #6169.

}
}

static boolean isExpired(Long expiresAtMillis, long now) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why I didn't add a method like this is that it isn't correct when expiresAtMillis is null. It returns false, but the token may still be expired. I think it's misleading to have a method with this name, so I think we should revert the change to add this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for bringing this up. I'll look into that as part of #6562

@rdblue rdblue merged commit ab1a19b into apache:master Jan 17, 2023
@rdblue
Copy link
Contributor

rdblue commented Jan 17, 2023

I think that we need to fix https://github.com/apache/iceberg/pull/6489/files#r1072451113 in a follow-up, but that's minor so I'm going to merge this to unblock the next steps. Thanks, @nastra!

@nastra nastra deleted the rest-catalog-token-refresh branch January 17, 2023 16:56
krvikash pushed a commit to krvikash/iceberg that referenced this pull request Mar 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants