If the user has an account then I generally use SecureRandom to generate a random url-safe string then put that in the db associated with the user and an expiry, then in the URL params I will add the user’s ID as well as the generated string, that way the ID must correspond with the string, or it won’t work
There’s an Elixir library for SecureRandom:
iex> SecureRandom.urlsafe_base64
"xYQcVfWuq6THMY_ZVmG0mA"