Skip to content

Change AllocationToken behavior in non-catastrophic situations #2730

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

Merged
merged 1 commit into from
Apr 23, 2025

Conversation

gbrodman
Copy link
Collaborator

@gbrodman gbrodman commented Mar 27, 2025

We're changing the way that allocation tokens work in suboptimal (i.e. incorrect) situations in the domain check, creation, and renewal process. Currently, if a token is not applicable, in any way, to any of the operations (including when a check has multiple operations requested) we return some variation of "Allocation token not valid" for all of those options. We wish to allow for a more lenient process, where if a token is "not applicable" instead of "invalid", we just pass through that part of the request as if the token were not there.

Types of errors that will remain catastrophic, where we'll basically return a token error immediately in all cases:

  • nonexistent or null token
  • token is assigned to a particular domain and the request isn't for that domain
  • token is not valid for this registrar
  • token is a single-use token that has already been redeemed
  • token has a promotional schedule and it's no longer valid

Types of errors that will now be a silent pass-through, as if the user did not issue a token:

  • token is not allowed for this TLD
  • token has a discount, is not valid for premium names, and the domain name is premium
  • token does not allow the provided EPP action

Currently, the last three types of errors cause that generic "token invalid" message but in the future, we'll pass the requests through as if the user did not pass in a token. This does allow for a default token to apply to these requests if available, meaning that it's possible that a single DomainCheckFlow with multiple check requests could use the provided token for some check(s), and a default token for others.

The flip side of this is that if the user passes in a catastrophically invalid token (the first five error messages above), we will return that result to any/all checks that they request, even if there are other issues with that request (e.g. the domain is reserved or already registered).

See b/315504612 for more details and background


This change is Reviewable

@gbrodman gbrodman force-pushed the partValidToken branch 6 times, most recently from 6a3e86c to 852cded Compare March 28, 2025 19:41
@CydeWeys
Copy link
Member

CydeWeys commented Apr 1, 2025

I still don't think it's a good idea to silently ignore situations where the token is inapplicable due to TLD or EPP action mismatch, especially on creates (you can just imagine the incoming support requests where an entire month's worth of creates is done at the standard price instead of some discount and then they get the monthly invoice and want us to retroactively fix things). This is really what registrars want? And this is how other registries handle tokens?

@gbrodman
Copy link
Collaborator Author

gbrodman commented Apr 1, 2025

I still don't think it's a good idea to silently ignore situations where the token is inapplicable due to TLD or EPP action mismatch, especially on creates (you can just imagine the incoming support requests where an entire month's worth of creates is done at the standard price instead of some discount and then they get the monthly invoice and want us to retroactively fix things). This is really what registrars want? And this is how other registries handle tokens?

I'm less concerned about EPP action mismatch, both because most tokens tend to be CREATE only anyway and registrars often want to issue domain:check requests for create / renew / update all at once.

The TLD mismatch is a fair point -- let's discuss this as a group next meeting

@gbrodman gbrodman requested a review from CydeWeys April 15, 2025 14:33
Copy link
Member

@CydeWeys CydeWeys left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 22 files reviewed, 2 unresolved discussions


core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java line 240 at r1 (raw file):

    } catch (AllocationTokenFlowUtils.NonexistentAllocationTokenException
        | AllocationTokenFlowUtils.AllocationTokenInvalidException e) {
      // The provided token was catastrophically invalid in some way

Is it worth logging here?
And we're really just gonna ignore a non-existent allocation token?


core/src/main/java/google/registry/flows/domain/token/AllocationTokenFlowUtils.java line 60 at r1 (raw file):

  /** Don't apply discounts on premium domains if the token isn't configured that way. */
  public static boolean discountTokenInvalidForPremiumName(

Clearer to phrase this in the positive sense and name is isTokenValidForPremiumName().

Copy link
Collaborator Author

@gbrodman gbrodman left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 22 files reviewed, 2 unresolved discussions (waiting on @CydeWeys)


core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java line 240 at r1 (raw file):

Is it worth logging here?

I was thinking that this could result in multiple copies of the same log line if the client uses a catastrophically invalid token on a domain:check action with multiple domains but eh, that's probably 1. not a big deal 2. not common

And we're really just gonna ignore a non-existent allocation token?

What do you mean by "ignore"? We're not ignoring it at all, the non-empty message signifies the failure case (same as before, https://github.com/google/nomulus/blob/master/core/src/main/java/google/registry/flows/domain/token/AllocationTokenFlowUtils.java#L62-L68)


core/src/main/java/google/registry/flows/domain/token/AllocationTokenFlowUtils.java line 60 at r1 (raw file):

Previously, CydeWeys (Ben McIlwain) wrote…

Clearer to phrase this in the positive sense and name is isTokenValidForPremiumName().

The guidelines generally say to use positive phrasing but that doesn't work neatly here. This only kicks in if the token has a discount AND the domain is premium AND the token is not valid for premium domains -- if all those are true, then the caller short-circuits.

Or, put another way, isTokenValidForPremiumName is not the opposite of discountTokenInvalidForPremiumName (both would return false if the domain is not premium + the token is not premium)

Copy link
Member

@CydeWeys CydeWeys left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 22 files reviewed, 2 unresolved discussions


core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java line 244 at r2 (raw file):

        | AllocationTokenFlowUtils.AllocationTokenInvalidException e) {
      // The provided token was catastrophically invalid in some way
      logger.atInfo().withCause(e).log("Cannot load/use allocation token");

Nit, but, log lines should end with periods or other punctuation so it's easier to tell when a given logged message ends when looking at the logs (which may have line-wrapping going on depending on where you're looking at it). Also it'd be nice to log the token that failed to load here.

Copy link
Member

@CydeWeys CydeWeys left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewable status: 0 of 22 files reviewed, 2 unresolved discussions (waiting on @gbrodman)

Copy link
Collaborator Author

@gbrodman gbrodman left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 22 files reviewed, 2 unresolved discussions (waiting on @CydeWeys)


core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java line 244 at r2 (raw file):

Previously, CydeWeys (Ben McIlwain) wrote…

Nit, but, log lines should end with periods or other punctuation so it's easier to tell when a given logged message ends when looking at the logs (which may have line-wrapping going on depending on where you're looking at it). Also it'd be nice to log the token that failed to load here.

Given that we don't have direct access to the token here (all we have is the EPP input) i'm disinclined to parse out the token here, especially since we log all EPP request inputs anyway (so we still have the token logged somewhere).

. added

We're changing the way that allocation tokens work in suboptimal (i.e. incorrect) situations in the domain check, creation, and renewal process. Currently, if a token is not applicable, in any way, to any of the operations (including when a check has multiple operations requested) we return some variation of "Allocation token not valid" for all of those options. We wish to allow for a more lenient process, where if a token is "not applicable" instead of "invalid", we just pass through that part of the request as if the token were not there.

Types of errors that will remain catastrophic, where we'll basically return a token error immediately in all cases:
- nonexistent or null token
- token is assigned to a particular domain and the request isn't for that domain
- token is not valid for this registrar
- token is a single-use token that has already been redeemed
- token has a promotional schedule and it's no longer valid

Types of errors that will now be a silent pass-through, as if the user did not issue a token:
- token is not allowed for this TLD
- token has a discount, is not valid for premium names, and the domain name is premium
- token does not allow the provided EPP action

Currently, the last three types of errors cause that generic "token invalid" message but in the future, we'll pass the requests through as if the user did not pass in a token. This does allow for a default token to apply to these requests if available, meaning that it's possible that a single DomainCheckFlow with multiple check requests could use the provided token for some check(s), and a default token for others.

The flip side of this is that if the user passes in a catastrophically invalid token (the first five error messages above), we will return that result to any/all checks that they request, even if there are other issues with that request (e.g. the domain is reserved or already registered).

See b/315504612 for more details and background
@gbrodman gbrodman added this pull request to the merge queue Apr 23, 2025
Merged via the queue into google:master with commit 56cd2ad Apr 23, 2025
8 of 9 checks passed
@gbrodman gbrodman deleted the partValidToken branch April 23, 2025 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants