You would not want an unsubscribe link like https://www.mydomain.com/[email protected]
.
- The Email is visible and a potential privacy concern
- Malicious user could potentially unsubscribe any email by passing in the email paramater
Solution 1: Encrypt using JWT
You might want to encrypt the email with any crypto algorithm you deemed fit, or you could use JWT.
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
Though we are not exactly using JWT for its intended purpose, but it is capable of encrypt/decrpt data using a standardise way supported on many languages.
Edit requirements.txt
or install via pip install PyJWT
.
# https://pypi.org/project/PyJWT/
PyJWT==1.7.1
Generate token
import jwtimport timeSECRET = "..."token = jwt.encode({'email': email, 'time': int(time.time())}, SECRET, algorithm='HS256').decode('utf-8')unsubscribe_url = f"https://www.mydomain.com/unsubsribe?token={token}"
NOTE: To prevent potential reservse engineering, you can add a random or time parameter.
Handle Unsubscribe
def unsubscribe_request_invite(request): token = request.args.get('token') if not token: abort(400, 'Missing token') try: data = jwt.decode(token, UNSUBSCRIBE_REQUEST_INVITE_SECRET, algorithms=['HS256']) except jwt.exceptions.DecodeError: abort(400, 'Invalid token') if 'email' not in data: abort(400, 'Missing data') email = data['email'] # do something return render_template('unsubscribe.html', email=email)
NOTE: You could also attach additional data such as expiry date to make this token valid for N days only.
Solution 2: ID
Rather than using email
as parameter, you can use the document id to handle unsubcribe (query database for the ID to process unsubsribe).
NOTE: Make sure the document id is not easily guessable, such as 1, 2, 3, etc
.
NOTE: Make sure all document id isn't exposed publicly.
Solution 3: Hash
You could either hash the email or document id as query parameter, and query database using the hash to process unsubscribe.
NOTE: Hash could not be reversed to retrieve the original value, so you need to store the hash in database for query.
import hashlibSALT = 'SOME SECRET'email = '[email protected]'doc_id = 'xbF...'token = hashlib.sha256((email + doc_id + SALT).encode('utf-8')).hexdigest()