Mojolicious-Plugin-BasicAuthPlus

 view release on metacpan or  search on metacpan

lib/Mojolicious/Plugin/BasicAuthPlus.pm  view on Meta::CPAN


    # realm, pass, user || realm, pass, undef || realm, callback
    return $realm, reverse @_;
}

sub _password_prompt {
    my ($self, $c, $realm) = @_;

    $c->res->headers->www_authenticate("Basic realm=\"$realm\"");
    $c->res->code(401);
    $c->rendered;

    return;
}

sub _split_auth {
    # Split $auth into username and password (which may contain ":")
    my ($username, $password) = split ':', $_[0], 2;

    $username = '' unless defined $username;
    $password = '' unless defined $password;

    return ($username, $password);
}

sub _check_simple {
    my ($self, $c, $auth, $params) = @_;
    my ($username, $password) = _split_auth($auth);

    return 1
        if $username eq $params->{'username'}
        and Authen::Simple::Password->check($password, $params->{'password'});
}

sub _check_ldap {
    my ($self, $c, $auth, $params) = @_;
    my ($username, $password) = _split_auth($auth);
    my $logging = $params->{logging} // 0;

    return 0 unless defined $password;

    my $ldap = Net::LDAP->new(
        $params->{host},
        port    => $params->{port} // 389,
        scheme  => $params->{scheme} // 'ldap',
        debug   => $params->{debug} // 0,
        timeout => $params->{timeout} // 120,
        version => $params->{version} // 3,
    );
    unless ($ldap) {
        $c->app->log->warn("Connection to $params->{host} failed: $@")
            if $logging;
        return 0;
    }

    my $socket_type = ref $ldap->{net_ldap_socket};
    $c->app->log->warn("LDAP socket type: $socket_type") if $logging;

    unless (
        # SSL connection already established
        ($socket_type eq 'IO::Socket::SSL')

        # Or user doesn't want TLS
        || (defined($params->{start_tls}) && $params->{start_tls} == 0)
        )
    {
        my $dse     = $ldap->root_dse();
        my $has_tls = $dse->supported_extension('1.3.6.1.4.1.1466.20037');

        if ($has_tls) {
            my $mesg = $ldap->start_tls(
                verify => $params->{tls_verify} // 'optional',
                cafile => $params->{cafile} // '',
            );
            if ($mesg->is_error) {
                my $text = "start_tls() failed for $params->{host}. "
                    . "[$mesg->code] $mesg->error_name: $mesg->error_text";
                $c->app->log->warn($text) if $logging;
                $ldap->unbind;
                return 0;
            }
        }

        $socket_type = ref $ldap->{net_ldap_socket};
        $c->app->log->warn("LDAP socket type after start_tls(): $socket_type")
            if $logging;
    }

    my @credentials
        = $params->{binddn}
        ? ($params->{binddn}, password => $params->{bindpw})
        : ();

    my $mesg = $ldap->bind(@credentials);
    if ($mesg->is_error) {
        $c->app->log->warn("LDAP bind failed"
                . ($params->{binddn} ? " for $params->{binddn}: " : ": ")
                . $mesg->error)
            if $logging;
        $ldap->unbind;
        return 0;
    }

    my $count = () = $params->{filter} =~ /%s/g;
    my $filter = sprintf($params->{filter}, ($username) x $count);
    my $scope  = $params->{scope} // 'sub';
    my $search = $ldap->search(
        base   => $params->{basedn},
        scope  => $scope,
        filter => $filter,
        attrs  => ['1.1']
    );

    if ($search->is_error) {
        $c->app->log->warn("LDAP search failed: " . $search->error)
            if $logging;
        $ldap->unbind;
        return 0;
    }

    if ($search->count == 0) {



( run in 0.527 second using v1.01-cache-2.11-cpan-39bf76dae61 )