<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package Catalyst::Authentication::Credential::MultiFactor;

use strict;
use warnings;
use 5.01.102;

use Moose;

our $VERSION = '1.2';

has config =&gt; (is =&gt; 'ro', required =&gt; 1);
has factors =&gt; (is =&gt; 'ro', default =&gt; sub { [] });

sub BUILDARGS {
  my ($class, $config, $app, $realm) = @_;
  { config =&gt; $config, app =&gt; $app, realm =&gt; $realm };
}

sub BUILD {
  my ($self, $args) = @_;

  my ($app, $realm) = @{$args}{qw(app realm)};
  
  foreach my $factor (@{$self-&gt;config-&gt;{'factors'}}) {

    my $credential_class  = $factor-&gt;{'class'};

    if ($credential_class !~ /^\+(.*)$/ ) {
      $credential_class = "Catalyst::Authentication::Credential::${credential_class}";
    } else {
      $credential_class = $1;
    }
    
    Catalyst::Utils::ensure_class_loaded( $credential_class );

    $app-&gt;log-&gt;debug('LOADED class: '.$credential_class) if $app-&gt;debug;
    push @{$self-&gt;factors}, $credential_class-&gt;new($factor, $app, $realm);
  
  }
}

sub authenticate {
  my ($self, $c, $realm, $authinfo) = @_;
  
  my $user_obj;
  
  foreach my $factor (@{$self-&gt;factors}) {
    $c-&gt;log-&gt;debug('Trying to authenticate agains '.$factor) if $c-&gt;debug;
    return unless eval { $user_obj = $factor-&gt;authenticate($c, $realm, $authinfo) };
    $c-&gt;log-&gt;debug('Authentication successful against '.$factor) if $c-&gt;debug;
  }
  return $user_obj;
}

1;
__END__


=head1 NAME

Catalyst::Authentication::Credential::MultiFactor

=head VERSION

Version 1.2

=head1 DESCRIPTION

Provides multi-factor authentication to your Catalyst app
Uses the Catalyst::Plugin::Authentication system.

=head1 SYNOPSIS

  use Catalyst qw(
    ...
    Authentication
    ...
    );

  __PACKAGE__-&gt;config(
    name =&gt; 'myApp',

    ....

    'Plugin::Authentication' =&gt; {
      ...
      default =&gt; {
        credential =&gt; {
          class =&gt; 'MultiFactor',                                                                                                                                                                                                                                  
          factors  =&gt; [
            {
              class        =&gt; 'YubiKey',
              api_id       =&gt; 1337,
              api_key      =&gt; 'foo/BAr/baz818=',
            },
            {
              class         =&gt; 'Password',
              user_model    =&gt; 'DB::login',
              password_type =&gt; 'self_check',
            },
            .... add more plugins!
          ],
        },
      },
    },
  );

=head1 INSTALLATION

  To install this module type the following:

   perl Makefile.PL
   make
   make test
   make install

=head1 DEPENDENCIES

  This module requires these other modules and libraries:

  Moose
  namespace::autoclean

=head 1COPYRIGHT AND LICENCE

  Copyright (C) 2012 by CÃ©dric Jeanneret

  This library is free software; you can redistribute it and/or modify
  it under the same terms as Perl itself, either Perl version 5.14.2 or,
  at your option, any later version of Perl 5 you may have available.

=cut
</pre></body></html>