summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Stocker <me@chregu.tv>2011-02-21 22:06:55 +0100
committerChristian Stocker <me@chregu.tv>2011-02-21 22:06:55 +0100
commitdeb9eb105fbd7705dee5d24826314c944a406a5e (patch)
treeb7203b0880bc7362c3a573bebb1e3d4c058d0030
parentb17118215119b748a19c3b4066acf23a57527445 (diff)
downloadGoogleAuthenticator.php-deb9eb105fbd7705dee5d24826314c944a406a5e.zip
GoogleAuthenticator.php-deb9eb105fbd7705dee5d24826314c944a406a5e.tar.gz
GoogleAuthenticator.php-deb9eb105fbd7705dee5d24826314c944a406a5e.tar.bz2
Added real world example (not security tested yet :))
-rw-r--r--README6
-rw-r--r--tmpl/ask-for-otp.php11
-rw-r--r--tmpl/loggedin.php19
-rw-r--r--tmpl/login-error.php6
-rw-r--r--tmpl/login.php8
-rw-r--r--tmpl/show-qr.php12
-rw-r--r--users.dat1
-rw-r--r--web/Users.php134
-rw-r--r--web/index.php86
9 files changed, 282 insertions, 1 deletions
diff --git a/README b/README
index cb09554..601f797 100644
--- a/README
+++ b/README
@@ -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. \ No newline at end of file
+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. \ No newline at end of file
diff --git a/tmpl/ask-for-otp.php b/tmpl/ask-for-otp.php
new file mode 100644
index 0000000..4d69c77
--- /dev/null
+++ b/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> \ No newline at end of file
diff --git a/tmpl/loggedin.php b/tmpl/loggedin.php
new file mode 100644
index 0000000..661b546
--- /dev/null
+++ b/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> \ No newline at end of file
diff --git a/tmpl/login-error.php b/tmpl/login-error.php
new file mode 100644
index 0000000..a8fedfd
--- /dev/null
+++ b/tmpl/login-error.php
@@ -0,0 +1,6 @@
+<p>
+Wrong username or password or token.
+</p>
+<p>
+<a href="./">try again</a>
+</p> \ No newline at end of file
diff --git a/tmpl/login.php b/tmpl/login.php
new file mode 100644
index 0000000..bbce13b
--- /dev/null
+++ b/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> \ No newline at end of file
diff --git a/tmpl/show-qr.php b/tmpl/show-qr.php
new file mode 100644
index 0000000..bdb00a1
--- /dev/null
+++ b/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> \ No newline at end of file
diff --git a/users.dat b/users.dat
new file mode 100644
index 0000000..fdcc130
--- /dev/null
+++ b/users.dat
@@ -0,0 +1 @@
+{"chregu":{"password":"foobar"}} \ No newline at end of file
diff --git a/web/Users.php b/web/Users.php
new file mode 100644
index 0000000..c794537
--- /dev/null
+++ b/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;
+
+ }
+
+}
+?>
diff --git a/web/index.php b/web/index.php
new file mode 100644
index 0000000..1a4c9e7
--- /dev/null
+++ b/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> \ No newline at end of file