Skip to content

Commit

Permalink
Added real world example (not security tested yet :))
Browse files Browse the repository at this point in the history
  • Loading branch information
chregu committed Feb 21, 2011
1 parent b171182 commit deb9eb1
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 1 deletion.
6 changes: 5 additions & 1 deletion README
Expand Up @@ -7,4 +7,8 @@ PHP app (Of course, you can also create them with this).

There are many real world applications for that, but noone implemented it yet.

See example.php for how to use it.
See example.php for how to use it.

There's a little web app showing how it works in web/, please make users.dat
writeable for the webserver, doesn't really work otherwise (it can't save the
secret). Try to login with chregu/foobar.
11 changes: 11 additions & 0 deletions tmpl/ask-for-otp.php
@@ -0,0 +1,11 @@

<h1>please otp</h1>
<p>
<form method="post" action="./">
otp: <input name="otp"
value="<?php
$g = new GoogleAuthenticator();

echo $g->getCode($user->getSecret());?>"/><br/>
<input type="submit"/>
</form>
19 changes: 19 additions & 0 deletions tmpl/loggedin.php
@@ -0,0 +1,19 @@

<p>
Hello <?php echo $user->getUsername(); ?>
</p>
<?php
if (!isset($_GET['showqr'])) {
?>

<p>
<a href="?showqr=1">Show QR Code</a>
</p>

<?php
}
?>

<p>
<a href="?logout=1">Logout</a>
</p>
6 changes: 6 additions & 0 deletions tmpl/login-error.php
@@ -0,0 +1,6 @@
<p>
Wrong username or password or token.
</p>
<p>
<a href="./">try again</a>
</p>
8 changes: 8 additions & 0 deletions tmpl/login.php
@@ -0,0 +1,8 @@

<h1>please login</h1>
<p>
<form method="post" action="./">
username: <input name="username"/><br/>
password: <input name="password" type="password"/><br/>
<input type="submit"/>
</form>
12 changes: 12 additions & 0 deletions tmpl/show-qr.php
@@ -0,0 +1,12 @@
<h1>Please scan this </h1>

<p> with <a href="http://www.google.com/support/a/bin/answer.py?hl=en&answer=1037451">the Google Authenticator App</a></p>

<p>
<?php
$g = new GoogleAuthenticator();
$link = $g->getUrl($user->getUsername(),$_SERVER['HTTP_HOST'],$secret);
?>

<a href="<?php echo $link;?>"><img style="border: 0; padding:10px" src="<?php echo $link;?>"/></a>
</p>
1 change: 1 addition & 0 deletions users.dat
@@ -0,0 +1 @@
{"chregu":{"password":"foobar"}}
134 changes: 134 additions & 0 deletions web/Users.php
@@ -0,0 +1,134 @@
<?php

class Users {


function __construct($file = "../users.dat") {
$this->userFile = $file;

$this->users = json_decode(file_get_contents($file),true);
}
function hasSession() {
session_start();
if (isset($_SESSION['username'])) {
return $_SESSION['username'];
}
return false;
}


function storeData(User $user) {
$this->users[$user->getUsername()] = $user->getData();
file_put_contents($this->userFile,json_encode($this->users));
}

function loadUser($name) {
if (isset($this->users[$name])) {

return new User($name,$this->users[$name]);
} else {
return false;
}
}



}

class User {

function __construct($user,$data) {
$this->data = $data;
$this->user = $user;
}

function auth($pass) {
if ($this->data['password'] === $pass) {
return true;
}

return false;

}

function startSession() {

$_SESSION['username'] = $this->user;
}

function doLogin() {
session_regenerate_id();
$_SESSION['loggedin'] = true;
}

function doOTP() {
$_SESSION['OTP'] = true;
}

function isOTP() {
if (isset($_SESSION['OTP']) && $_SESSION['OTP'] == true) {

return true;
}
return false;

}
function isLoggedIn() {
if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] == true) {

return $_SESSION['username'];
}
return false;

}


function getUsername() {
return $this->user;
}

function getSecret() {
if (isset($this->data['secret'])) {
return $this->data['secret'];
}
return false;
}

function generateSecret() {
$g = new GoogleAuthenticator();
$secret = $g->generateSecret();
$this->data['secret'] = $secret;
return $secret;

}

function getData() {
return $this->data;
}

function setOTPCookie() {
$time = floor(time() / (3600 * 24) ); // get day number
$cookie = $time.":".sha1($this->getUsername().":".$time.":".$this->getSecret());
setcookie ( "otp", $cookie, time() + (30 * 24 * 3600), null,null,null,true );
}

function hasValidOTPCookie() {
// 0 = tomorrow it is invalid
$daysUntilInvalid = 0;
$time = (string) floor((time() / (3600 * 24))) ; // get day number
if (isset($_COOKIE['otp'])) {
list( $otpday,$hash) = explode(":",$_COOKIE['otp']);

if ( $otpday >= $time - $daysUntilInvalid && $hash == sha1($this->getUsername().":".$otpday .":" . $this->getSecret())
) {
return true;
}


}
return false;

}

}
?>
86 changes: 86 additions & 0 deletions web/index.php
@@ -0,0 +1,86 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="generator" content=
"HTML Tidy for Mac OS X (vers 31 October 2006 - Apple Inc. build 15.3.6), see www.w3.org" />
<title></title>
</head>
<body>
<?php
ini_set("session.cookie_httponly", 1);
include_once("../lib/GoogleAuthenticator.php");
include_once("Users.php");



$users = new Users();
if ($username = $users->hasSession()) {
$user = $users->loadUser($username);
if (isset($_GET['logout'])) {
session_destroy();
header("Location: ./");
}
if ($user->isLoggedIn()) {
include("../tmpl/loggedin.php");
if (isset($_GET['showqr'])) {
$secret = $user->getSecret();
include("../tmpl/show-qr.php");
}
} else if ($user->isOTP() && isset($_POST['otp'])) {
$g = new GoogleAuthenticator();
if ($g->checkCode($user->getSecret(),$_POST['otp'])) {
$user->doLogin();
$user->setOTPCookie();
include("../tmpl/loggedin.php");
} else {
session_destroy();
include("../tmpl/login-error.php");
}

} else {
session_destroy();
}



die();
} else if (isset($_POST['username'])) {
$user = $users->loadUser($_POST['username']);

if ($user) {
if ($user->auth($_POST['password'])) {
$user->startSession();
if ($user->hasValidOTPCookie()) {
include("../tmpl/loggedin.php");
$user->doLogin();

} else if (!$user->getSecret()) {
include("../tmpl/loggedin.php");

$secret = $user->generateSecret();
$users->storeData($user);
$user->doLogin();
include("../tmpl/show-qr.php");

} else {
$user->doOTP();
include("../tmpl/ask-for-otp.php");
}


die();
}
}
session_destroy();

include("../tmpl/login-error.php");
die();
}

include("../tmpl/login.php");


?>
</body>
</html>

0 comments on commit deb9eb1

Please sign in to comment.