Jump to content

Login with a link (is it called magic link?)


Ivan Gretsky
 Share

Recommended Posts

Good day!

I am looking for a solution to do a login-with-a link functionality. A site should generate and send via email a link to a user. That link should contain (as I can imagine) a login and some kind of token. Following that link a user is able to get automatically authenticated on a site and view the page, otherwise inaccessible.

 

Link to comment
Share on other sites

The whole process is not that difficult. Create a long random string and store in in the db. When a link is hit, check the db for that token and if found (and still valid?) login the user and delete the token from the db. The only real pain point could be the "create a random string" part depending on how secure the whole thing should be.

  • Like 3
Link to comment
Share on other sites

Yes, that is the route I will probably take. I think about storing the token in the user template and use it only in pair with login. I am planning to use forceLogin to authenticate without password on condition if the token in the url matches the token stored in the user template.

Link to comment
Share on other sites

@Ivan Gretsky, there is a crypto module here that can create random token strings for you.

If I remember correctly, you can just do this;

$num_chars  = 32; // The length of the token you want. Adjust as needed 
$random_key = CryptoPPP::genKeys(1);  // Generates a seed key
$token      = CryptoPPP::keyToToken($random_key, $num_chars); // Convert to string token

You can also define the character set that the random string is to use if you aren't happy with the default one. In fact, if you are going to use the token in a returned link, you'll definitely want to change the default character set used in the generation to only use url-safe characters.

  • Like 6
Link to comment
Share on other sites

  • 5 months later...
  • 10 months later...

Ok.

1. We need to generate a unique token for a user and store it. The simple way to do that is to add a field to user page (login_token in the example). To make process easier we make a method for that via hook:

// site/init.php

$wire->addHook("User()::getToken", function(HookEvent $event) {
	$page = $event->object;
	if (empty($page->login_token)) {
		$page->of(false);
		$page->login_token = generateToken(12);
		$page->save();
		$page->of(true);
	}
	return $event->return = $page->login_token;
});

The genereateToken() function is yours to implement as you wish.

2. Now we can generate a link:

$link = $page->httpUrl . "?user=". $user->id . "&token=". $user->getToken();

3. Finally we need to handle those parameters and make user autologin:

// site/templates/_init.php

if ($userToLoginId = $sanitizer->int($input->get->user)) {
	
	$url = $page->url;
	$userToLogin = $users->get($userToLoginId);
	$tokenToLoginWith = $sanitizer->text($input->get->token);
	
	if ($userToLogin->id && $tokenToLoginWith && strcmp($userToLogin->login_token, $tokenToLoginWith) == 0) {
		$loggedInUser = $session->forceLogin($userToLogin);
		if ($loggedInUser) {
			$user = $loggedInUser;
		};
		$session->redirect($url);
	}
}

We can then nullify user token if we want it to be only a one-time ticket.

I rewrote whole lot of stuff, so might not work  straight away, but surely you can fix it @szabesz)) Hope I am not missing something essential.

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...