-
Notifications
You must be signed in to change notification settings - Fork 308
Limit pending verifications in emails UI #4579
Conversation
I realized at #4571 (comment) that we can implement verification throttling with no additional schema changes by protecting against removal in the app layer. That's enough for here, though handling unsubscribes will still be a chore ... |
Squashed and rebased, was 1b1ee1e. |
1b1ee1e
to
a6fae92
Compare
@whit537: Comments added at #4571 (comment) |
a6fae92
to
153469b
Compare
Okay! First chunk of work done in 153469b. Since we're already at 370 ∆ lines I will probably scope this just to the email listing, and implement the package page and API changes on other PRs. |
Picking up from #4571 (comment) ...
Then they have to contact support. And that raises a good point: admins should be able to remove pending email verifications. If we get enough pressure on support then we consider re-enabling this as self-serve.
Sorry ... how so?
👍 |
I enter a wrong email address. Person verifies the email, uses it (forgot password + reset password using email) to sign-in? |
Okay, but how do we mitigate that? That's the achilles heel of email for auth, isn't it? :-/ |
Allow the user to remove the email immediately, by themselves. (We should also remove the verification token internally, when they do that) |
Okay, but then how do we protect against the other security risk: remove-and-add to work around verification throttling? |
Remember that verification links expire after 24 h anyway. We could tighten that to five minutes once we have instant send (#4545). |
Can't we maintain persistent history of sent emails separately, and use that info to throttle? Canceling of an email verification link doesn't have to necessary delete ALL history of an email ever being sent. |
Sorry, throttling isn't the best word. The way we're headed here is to do both:
|
I think we should tighten the verification window to five minutes: that will protect against "honest mistakes" turning into inadvertent phishing. I think we should only allow one pending verification at a time with no option to remove. Our use case is different than GitHub's because we have all npm maintainer emails in our system. We're playing with fire. 😳 🔥 |
Hmm, I see what you're getting at. |
I understand the 'limit pending verifications' concern. However, what does 'having all npm maintainer emails in our system' have to do with user email verification? Is this because it is tied to claiming packages? |
Yes. On my next PR I'll be modifying the UI on pages like https://gratipay.com/on/npm/express to limit the ability to initiate package claims when there are existing verifications (~= package claims) outstanding. |
We've had three users already report spam/phishing to us (#4557), so this isn't theoretical. |
I still think that we should decouple email verification and linking packages. What I propose is:
Now that the email only says 'link [email protected] to the abcd account on Gratipay' - it is (perceived as?) less dangerous. As all services do, we'll just add a note saying 'If this wasn't you, no action is required' at the bottom. Generic sign-up email spam is understandable, and won't startle users like an email saying 'May we receive money on your behalf'. |
Okay, so can we hash out the user flow on https://gratipay.com/on/npm/express, then? Do we display all maintainer emails and only allow the user to initiate a message to addresses they've already verified? Do we only display email addresses they've already verified? Do we offer to send an email verification right from the package page? Do we make them click over to the Emails page to add the address there? |
Basics, just to get things working:
Streamlining (building upon the above):
|
That's #4425. |
4f33932
to
64b3555
Compare
7f628f9
to
2bf4991
Compare
dfa177e
to
a6b4315
Compare
a6b4315
to
dd375b8
Compare
Rebased back onto |
www/~/%username/emails/index.spt
Outdated
for email in emails: | ||
i = 0 if email.address == participant.email_address else 1 if email.verified else 2 | ||
groups[i].append(email) | ||
emails = sum(groups, []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😃 Is this common usage?
Perils of not having flatten
in the std lib? :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's how to spell flatten
in Python. 🐭
www/~/%username/emails/index.spt
Outdated
|
||
emails = participant.get_emails() | ||
groups = [[], [], []] # primary, verified, unverified | ||
for email in emails: | ||
i = 0 if email.address == participant.email_address else 1 if email.verified else 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're essentially doing a sort_by(func)
action here, can't we use https://docs.python.org/3/library/functions.html#sorted with the key
param?
i.e. something like:
def get_sort_key(email):
if email.address == participant.email_address:
return 0
elif email.verified:
return 1
else:
return 2
sorted_emails = sorted(emails, key=get_sort_key)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks less cryptic to me than the awkward spelling of flatten
, and the inlined inline if
😛
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 11a93a4
from gratipay.testing import BrowserHarness, QueuedEmailHarness | ||
|
||
|
||
class Row(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat!
dd375b8
to
c3452ab
Compare
- don't want before.py (see deploy/README) - run after.py directly on dyno vs. redirect
- dodge race condition around clicks and page reloading - factor out helpers into proper classes - simplify remove action to maintain proper state (presence of add form) - minor formatting tweak in sptfile
Rebased, previous head was @c3452ab8472658a42f2acdefa5cd865bbb645f33. |
c3452ab
to
8eb5d0e
Compare
@whit537 This looks good to me. Ready to merge? |
@rohitpaulk Yes! |
← Implement deploy hooks (#4590) — Redux of #4571 — "Ready to verify" (#4584) →
We want to limit pending email address verification attempts to one, to prevent abuse (#4557). We need to do this both in the UI and in the API/db. The former is in some ways easier than the latter so let's try starting with that?
Todo
confirm on remove→ Confirm some things #4581master
after Implement deploy hooks #4590