- Login with email link that contain token
- Receive 6 digits code by email
Created
March 16, 2021 17:45
-
-
Save arnoclr/ead8ea88e645bb482d5886da64007143 to your computer and use it in GitHub Desktop.
PHP Standalone login page without password
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
session_start(); | |
$token = str_replace('+', '_', base64_encode(openssl_random_pseudo_bytes(24))); | |
$step = 1; | |
function hideEmail($email) { | |
$parts = explode('@', $email); | |
return substr($parts[0], 0, min(3, strlen($parts[0])-3)) . str_repeat('*', max(3, strlen($parts[0]) - 3)) . '@' . $parts[1]; | |
} | |
function login() { | |
$_SESSION['user']['email'] = $_SESSION['loginEmail']; | |
} | |
// logout | |
if(isset($_GET['logout'])) { | |
unset($_SESSION['user']); | |
unset($_SESSION['loginEmail']); | |
header('location: /'); | |
exit; | |
} | |
// send 6 digits code | |
else if(isset($_GET['requestCode']) && isset($_SESSION['loginEmail'])) { | |
$code = random_int(100000, 999999); | |
$_SESSION['loginCode'] = $code; | |
$email = $_SESSION['loginEmail']; | |
if(mail($email, "CODE : $code", "$code is your verification code for https://$_SERVER[HTTP_HOST]")) { | |
$step = 3; | |
} else { | |
$error = "Unable to send email, check your address or try again later."; | |
} | |
} | |
// verify 6 digits code | |
else if(isset($_POST['code']) && isset($_SESSION['loginCode'])) { | |
$lastCode = $_SESSION['loginCode']; | |
$currentCode = $_POST['code']; | |
if($lastCode == $currentCode) { | |
login(); | |
} else { | |
unset($_SESSION['loginCode']); | |
$error = "invalid code, please retry"; | |
} | |
} | |
// send login link | |
else if(isset($_POST['email'])) { | |
$email = $_POST['email']; | |
if(filter_var($email, FILTER_VALIDATE_EMAIL)) { | |
$currentUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]"; | |
$loginLink = "$currentUrl?token=$token"; | |
$_SESSION['loginToken'] = $token; | |
$_SESSION['loginEmail'] = $email; | |
if(mail($email, 'Login link', "You have requested a login link, click below to connect to the website \n $loginLink")) { | |
$step = 2; | |
} else { | |
$error = "Unable to send email, check your address or try again later."; | |
} | |
} else { | |
$error = "Invalid email adress"; | |
} | |
} | |
// verify login link | |
else if(isset($_GET['token'])) { | |
$currentToken = $_GET['token']; | |
$lastToken = $_SESSION['loginToken']; | |
if($currentToken == $lastToken) { | |
login(); | |
} else { | |
unset($_SESSION['loginToken']); | |
$error = "Token mismatch"; | |
} | |
} | |
?> | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>mail login</title> | |
<link href="https://res.cloudinary.com/finnhvman/raw/upload/matter/matter-0.2.2.min.css" rel="stylesheet"> | |
<link rel="stylesheet" href="style.css"> | |
<link rel="preconnect" href="https://fonts.gstatic.com"> | |
<link href="https://fonts.googleapis.com/css2?family=Material+Icons&display=swap" rel="stylesheet"> | |
</head> | |
<body> | |
<main> | |
<form class="matter-card-outlined" method="post" action="/" onsubmit="document.getElementById('sub-btn').setAttribute('disabled', true)"> | |
<?php if(isset($_SESSION['user']['email'])): ?> | |
<section class="header"> | |
<i class="material-icons">account_circle</i> | |
<h1 class="matter-h4">Logged !</h1> | |
<p class="matter-body1">You can close this page. You're connected with <?= $_SESSION['user']['email'] ?> adress.</p> | |
</section> | |
<section class="bottom"> | |
<a class="matter-button-contained matter-error" href="?logout">sign out</a> | |
</section> | |
<?php else: if($step == 3): ?> | |
<section class="header"> | |
<i class="material-icons">dialpad</i> | |
<h1 class="matter-h4">Verification code</h1> | |
<p class="matter-body1">Code sent to <?= hideEmail($_SESSION['loginEmail']) ?></p> | |
</section> | |
<label class="matter-textfield-outlined"> | |
<input placeholder=" " name="code" type="number" min="100000" max="999999" required/> | |
<span>6 digits code</span> | |
</label> | |
<section class="bottom"> | |
<p></p> | |
<button class="matter-button-contained" id="sub-btn">login</button> | |
</section> | |
<?php else: if($step == 2): ?> | |
<section class="header"> | |
<i class="material-icons">link</i> | |
<h1 class="matter-h4">Login</h1> | |
<p class="matter-body1">Email sent to <?= hideEmail($_POST['email']) ?></p> | |
</section> | |
<section class="bottom"> | |
<p class="matter-body2">You can't open link on this device ? request a 6 digits code and use it on the next page.</p> | |
<a href="?requestCode" class="matter-button-outlined" id="sub-btn">request code</a> | |
</section> | |
<?php else: ?> | |
<section class="header"> | |
<i class="material-icons">account_circle</i> | |
<h1 class="matter-h4">Login</h1> | |
<p class="matter-body1">a connection link will be sent to you by email</p> | |
</section> | |
<label class="matter-textfield-outlined"> | |
<input placeholder=" " value="<?php if(isset($_POST['email'])) echo $_POST['email']; ?>" name="email" type="email" required/> | |
<span>email</span> | |
</label> | |
<section class="bottom"> | |
<p class="matter-body2">A link to connect will be sent to you by email. Login to this site does not require a password. <a href="#" class="matter-link">Learn more</a></p> | |
<?php if(isset($_SESSION['loginEmail'])): ?> | |
<p class="matter-body2">An email has been sent at <?= hideEmail($_SESSION['loginEmail']) ?></p> | |
<?php endif ?> | |
<button class="matter-button-contained" id="sub-btn">next</button> | |
</section> | |
<?php endif; endif; endif; ?> | |
<?php if(isset($error)): ?> | |
<p class="matter-body2 matter-error"><?= $error ?></p> | |
<?php endif ?> | |
</form> | |
<footer> | |
<a href="#" class="matter-body2">terms of service</a> | |
</footer> | |
</main> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin: 0; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
} | |
p.matter-error { | |
color: rgb(238,0,0) !important; | |
} | |
main { | |
} | |
form { | |
border: 1px solid rgb(150 150 150 / 30%); | |
border-radius: 8px; | |
padding: 48px 40px 80px; | |
width: 400px; | |
max-width: 80vw; | |
margin: 4px; | |
} | |
form .header { | |
text-align: center; | |
} | |
form .header i { | |
color: rgb(33,150,243); | |
font-size: 48px; | |
} | |
form label { | |
width: 100%; | |
} | |
form .bottom p { | |
color: grey; | |
} | |
form .bottom .matter-button-contained, | |
form .bottom .matter-button-outlined { | |
float: right; | |
text-decoration: none; | |
} | |
footer a { | |
color: grey; | |
text-decoration: none; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment