krgamestudios / auth-server

An API centric auth server.
zlib License
16 stars 2 forks source link

Add an unsubscribe link to emails #5

Open Ratstail91 opened 3 years ago

Ratstail91 commented 3 years ago

This is a requirement under certain jurisdictions - and is generally just polite.

This would just need a call to the auth-server to set the "contact" flag to false. However with anything, verification is important.

MatthewEvans91 commented 2 years ago

What emails does the system send out? Perhaps I am missing something, but from what I can see right now there are two: the welcome and forgot password communications. We couldn't block the 1st, and I don't think we really want to block the 2nd since it's a user-initiated action, etc.

Am I missing something, is there the ability for an admin to send out a group email?

Also -- where do you want this endpoint. I was thinking /auth/unsubscribe or something along those lines.

Ratstail91 commented 2 years ago

Hey Matthew! Yes, the validation and forgotten passwords are the only emails that are sent out at the current time. However, with my game Egg Trainer I plan on eventually having a big "It's Ready!" email sent out when it's finally reached my goal for it. An email like this would need an unsubscribe button, even if Egg Trainer's emails are really rare.

I figured that other people would also need some kind of way to allow one-click unsubscribes, so I added this as a feature on the backburner. So no, you're not missing anything.

/auth/unsubscribe would be an ideal endpoint for this feature - I'm just not sure where it would lead, or how it would work. Off the top of my (currently intoxicated) head, I think adding a token parameter associated with the account would be easiest:

https://auth.eggtrainer.com/auth/unsubscribe?token=uuid

Having a unique parameter like this would help prevent a malicious actor from unsubscribing everyone. You could stick it in a completely separate database table, and generate the emails programmatically. I'm not sure if there's a program out there that would insert a specific token for a specific address, but hey, we're software devs ;)

MatthewEvans91 commented 2 years ago

I think it's probably best to avoid maintaining a table in the database just to facilitate this. Each outbound email would generate a UUID which (I think) would need to be stored indefinitely.

If we generate a signed JWT as the token, the endpoint can simply verify/validate the JWT & pull the email to unsubscribe from the token itself.

I was also thinking that it may be a good idea to create a utility function to send these emails. Right now the function will simply generate and append the unsubscribe link; however, in the future it could be used to conform emails to a template, etc.

Here's what I've got right now:

Create API endpoint at /auth/unsubscribe requiring a JWT as a GET parameter. Endpoint is to verify/validate the JWT then use the email address in the JWT to unsubscribe any(all) user(s) with that email address by setting the contact flag to false for each matching user record.

Possibly:

Create utility function 'sendEmail(message, to, from)' This function will generate the JWT and append it to the message prior to sending. Refactor auth/password-recover.js, and auth/signup.js to use the utility function.

Ratstail91 commented 2 years ago

Right - actually I assumed we'd reuse the same token for different emails to the same recipient, but actually, a JWT would be way easier to manage - no having to mess with the database.

HOWEVER, one potential (and admittedly obscure) issue I see from using a JWT is that it would rely on the SECRET_ACCESS environment variable. This can and does change when you re-run configure-script.js for various reasons, unless you specifically go out of your way to make sure it remains the same. It's not a major problem making people re-login, but invalidating unsubscribe links might be.

The easiest solution might be to just not worry about it. Alternatively, adding an environment variable called SECRET_UNSUBSCRIBE and using that for the unsub JWT might be the best solution.

Finally, I don't actually think password-recover.js and signup.js need to be touched by this at all; those emails specifically don't need unsub links. I do think that a separate sendEmail() function might be needed, or at least a decorateEmail(), which inserts the unsub link into the message. I might eventually write an entire email utility just for this, if it's needed. It could be packaged under tools/.

It's shocking how much thought goes into just one feature like an unsub link. Are you planning on writing this yourself @MatthewEvans91? Or should I go ahead and start work on it?

MatthewEvans91 commented 2 years ago

@Ratstail91 Sorry for the delay -- took a break from anything work related for a couple of weeks. I would love to write this out, probably get around to it later this week or perhaps this weekend.

That's a good point about the JWT -- I'll give it some more thought. Updating the the JWT secret would only break old unsubscribe links, so perhaps a simple note to that effect in the configuration utility would suffice (eg: "take a note of this secret as updating it in the future will break old email unsubscribe links").

sendEmail() under tools/ would be useful. I'll plan out a module and get back here with that once I've thought it through.

Ratstail91 commented 2 years ago

No worries about the delay! I happen to have picked up an intern in those weeks though, so I'll rope @kcampbelljr into the conversation. He's working on engine stuff, so this might be a feature he can help with.

Ratstail91 commented 2 months ago

@foohonpie Thoughts on this feature?

It's not part of the sale contract, but you can mark it as a feature to merge post-hand off.

foohonpie commented 1 month ago

hi @Ratstail91, i'm planning on managing marketing emails through a unified system alongside my other projects. i won't need to bring this feature in post-handoff.

thanks for checking though 👍

Ratstail91 commented 1 month ago

No worries - I'll keep it open, as it'd be a neat feature for MERN in the future - feel free to unsub so you don't get notifications.