Going Password-Free

46093583d8895095adb1b0071c505af2?s=47 Eric Mann
February 03, 2017

Going Password-Free

Passwordless authentication via Tozny as presented at SunshinePHP 2017

46093583d8895095adb1b0071c505af2?s=128

Eric Mann

February 03, 2017
Tweet

Transcript

  1. 2.

    90

  2. 3.

    19

  3. 4.
  4. 5.
  5. 6.

    How can we fix it? Password managers help Password strength

    meters (zxcvbn) help Two-factor authentication helps But why require a password at all?
  6. 7.
  7. 8.

    A PHP Example Defer to a 3rd party for email

    & validation Use the SlimPHP framework for quick bootstrapping Allow either password or password-less authentication
  8. 10.

    Endpoints $app->get('/', function($request, $response, $args) {
 // Render index view


    return $this->renderer->render($response, 'index.phtml', $args);
 }); $app->get('/register', function($request, $response, $args) {
 // Render registration view
 return $this->renderer->render($response, ‘register.phtml', $args);
 }); $app->get('/authenticated', function($request, $response, $args) {
 // Render protected view
 return $this->renderer->render($response, ‘authenticated.phtml', $args);
 });
  9. 11.

    Endpoints $app->get('/authenticated', function($request, $response, $args) {
 if ( 
 !

    isset( $_SESSION['username'] ) || 
 ! $this->users->get( $_SESSION['username'] ) 
 ) {
 return $response->withRedirect('/?error=notloggedin');
 }
 
 // Render protected view
 return $this->renderer->render($response, ‘authenticated.phtml', $args);
 });
  10. 12.

    Endpoints $app->any('/login', function($request, $response, $args) {
 return $response->withRedirect('/?error=invalidlogin');
 }); $app->get('/logout',

    function($request, $response, $args) {
 session_destroy();
 
 return $response->withRedirect('/?loggedout');
 });
  11. 13.
  12. 14.

    Middleware class PasswordAuth {
 private $c;
 
 public function __construct($cont)

    {$this->c = $cont;}
 
 public function __invoke($req, $res, $next) {
 $user = $req->getParam(‘username’);
 $pass = $req->getParam(‘password’);
 
 if (empty($u) || empty($p)) return $res = $next($req, res);
 
 if ($this->c->validAuth($user, $pass)) {
 $_SESSION[‘username’] = $user;
 return $res = $res->withRedirect(‘/authenticated’);
 }
 return $res = $res->withRedirect(‘/?error=invalidlogin’);
 }
 }
  13. 16.

    Endpoints $app->any('/login', function($request, $response, $args) {
 if($request->getParam(‘magiclink’) && $request->getParam(‘username’)) {


    $user = $this->users->get($request->getParam(‘username’));
 $sent = sendMagicLink($user->email);
 
 if(‘ok’ === $sent[‘return’])
 return $response->withRedirect(‘/?message=checkemail’);
 }
 return $response->withRedirect('/?error=invalidlogin');
 })->add(new PasswordAuth($container));
  14. 17.

    Middleware class MagicLinkAuth {
 private $c;
 
 public function __construct($cont)

    {$this->c = $cont;}
 
 public function __invoke($req, $res, $next) {
 $toznyo = $req->getParam(‘toznyo’);
 $toznyr = $req->getParam(‘toznyr’);
 
 if (empty($toznyo) || empty($toznyr)) {
 $res = $next($req, res);
 } else {
 if ($this->c->validLink($toznyo, $toznyr) {
 $user = $this->c->users->getUserFromLink($toznyo);
 $_SESSION[‘username’] = $user->username;
 $res = $res->withRedirect(‘/authenticated’);
 }
 }
 return $res;
 }
 }
  15. 19.

    What just happened? Registered users can authenticate with their password

    Registered users can request a secure, one-time login link sent to their inbox The application doesn’t care which way the users authenticate
  16. 20.

    How does this benefit us? One less password for users

    to remember More flexible authentication schemes for existing users The middleware stack could be further extended to support TOTP/HOTP/ U2F/etc