grosv / laravel-passwordless-login

A simple, safe magic login link generator for Laravel
841 stars 60 forks source link

Invalidating links #80

Open ViolentlyViolet opened 2 years ago

ViolentlyViolet commented 2 years ago

Hi,

I was wondering if it was possible to invalidate a login link after an action was done by a user (eg, set a password). My current use case is that a user has to be approved before allowing them to login, and once the login link has been sent they need to set a password. Users will undoubtedly forget to set one so the link can be used multiple times. However, I would like to be able to invalidate a login link after a password has been set. Is this already possible but undocumented or would this be a new feature?

Edit: Something that could potentially be beneficial as well, is to be able to pass along a redirect URL on failing to login (expired link or the likes)

edgrosvenor commented 2 years ago

@RensenBart I can't think of a way to do this. The way one time use links work is that we write the link to the cache and just check to see if it's there. If it is, then we consider it invalid. The problem is where and how to hook in custom logic to know that "if x is true, check the cache to see if the link has been used".

I think the better fix is on the app side, to be honest. What I've done in the past is add a "password_set_at" timestamp to the users table and set that to null when a user is created. Once the user is approved and you send them their login link, either load their dashboard or, if password_set_at is still null, the form to set a password. Just don't let them go to their dashboard without setting their password.

As for the redirect to url on failed login, I'd definitely be open to a PR to add that.

alxndrmlr commented 1 year ago

I've been playing with this package today and was thinking a bunch about caching strategy (forgive me I'm quite new to Laravel only a couple weeks in).

It seems like this (as well as https://github.com/grosv/laravel-passwordless-login/issues/45) could be mitigated if the caching logic was changed.

Current Logic is roughly this

  1. Generate a link
  2. User obtains link (via email typically) and uses it
  3. On use cache the request
  4. On subsequent use check if it is in the cache (if yes abort)

Instead it seems we could do something like this

  1. Generate a link and cache the request
  2. User obtains link (via email typically) and uses it
  3. On use pop the request from the cache (or decrement a count attribute on it if it could be used multiple times re Issue #45
  4. On subsequent use check if it is in the cache (if no abort)
alxndrmlr commented 1 year ago

Notionally you could then expose a method to invalidedRequestForUser(...) which would just clear the cache of all links that are outstanding.

Waghabond commented 1 year ago

This could even be database driven - magic links typically should be database driven because then it keeps a historical record. This will also make the configurable number of uses easier