Skip to content

Instantly share code, notes, and snippets.

@arnoclr
Created March 16, 2021 17:45
Show Gist options
  • Save arnoclr/ead8ea88e645bb482d5886da64007143 to your computer and use it in GitHub Desktop.
Save arnoclr/ead8ea88e645bb482d5886da64007143 to your computer and use it in GitHub Desktop.
PHP Standalone login page without password

Standalone login page

  • Login with email link that contain token
  • Receive 6 digits code by email

screenshot

<?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>
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