Security Advisories (3)
CVE-2021-35472 (2021-07-30)

An issue was discovered in LemonLDAP::NG before 2.0.12. Session cache corruption can lead to authorization bypass or spoofing. By running a loop that makes many authentication attempts, an attacker might alternately be authenticated as one of two different users.

CVE-2021-35473

OAuth2 handler does not verify access token validity

CVE-2026-19349 (2026-08-16)

Lemonldap::NG::Portal versions from 2.0.0 before 2.16.9, from 2.17.0 before 2.21.5, from 2.22.0 before 2.23.3 for Perl allow authentication bypass via an OAuth2 state parameter stored as an SSO session in the GitHub and LinkedIn backends. Before redirecting to the identity provider, extractFormInfo() creates the state session with the positional call `getApacheSession( undef, 1, 0, 'GitHubState' )`. getApacheSession() takes a session id followed by a named argument hash, so the trailing arguments become that hash, `kind` defaults to SSO, and the state is written to the global session storage as a regular SSO session. Its identifier is handed to the unauthenticated visitor as the state parameter of the redirection URL. Any visitor who reaches the GitHub or LinkedIn endpoint can replay that identifier as a session cookie and obtain a valid SSO session without authenticating. The session holds neither _user nor authenticationLevel, which the shipped bootstrap configuration accepts because it grants virtual hosts a "default => accept" access rule; deployments whose rules test the user or require an authentication level are less exposed. Only configurations with the GitHub or LinkedIn authentication module enabled are affected.

NAME

Lemonldap:NG::Portal::Auth - Writing authentication modules for LemonLDAP::NG.

SYNOPSIS

package Lemonldap::NG::Portal::Auth::My;

use strict;
use Mouse;
# Add constants used by this module
use Lemonldap::NG::Portal::Main::Constants qw(PE_OK);

our $VERSION = '0.1';

# Directive provides by Mouse
extends 'Lemonldap::NG::Portal::Main::Auth';

sub init {
    ...
}

sub extractFormInfo {
    my ( $self, $req ) = @_;
    ...
}

sub authenticate {
    my ( $self, $req ) = @_;
    ...
}

sub setAuthSessionInfo {
    my ( $self, $req ) = @_;
    ...
}

sub authLogout {
    my ( $self, $req ) = @_;
    ...
}

sub getDisplayType {
    return ...;
}

1;

DESCRIPTION

Lemonldap::NG::Portal::Main::Auth must be used to build Lemonldap::NG authentication modules. Authentication modules are independent objects that are instantiated by Lemonldap::NG portal. They must provide methods described below.

METHODS

Accessors and methods provided by Lemonldap::NG::Portal::Main::Auth

p: portal object
conf: configuration hash (as reference)
logger alias for p->logger accessor
userLogger alias for p->userLogger accessor
error: alias for p->error method
authnLevel: Lemonldap::NG authentication level

"Routes" management

Like each module that inherits from Lemonldap::NG::Portal::Plugin, Lemonldap::NG::Portal::Main::Auth provides URI path functions:

addAuthRoute: wrapper to Lemonldap::NG::Handler::PSGI::Try addAuthRoute() method
addUnauthRoute: wrapper to Lemonldap::NG::Handler::PSGI::Try addUnauthRoute() method

Example:

sub init {
    ...
    $self->addAuthRoute( saml => { proxy => "proxySub" }, [ 'GET', 'POST' ] );
    ...
}
sub proxySub {
    my ( $self, $req ) = @_;
    ...
    # This sub must return a PSGI response. Example
    return [ 302, [ Location => 'http://x.y/' ], [] ];
}

This means that requests http://auth.../saml/proxy will be given to proxySub() method.

Methods that must be provided by an authentication module

init()

Method launched after object creation (after each configuration reload). It must return a true value if authentication module is ready, false else.

Methods called at each request

All these methods must return a Lemonldap::NG::Portal::Main::Constants value. They are called with one argument: a Lemonldap::NG::Portal::Main::Request object.

Note: if you want to change process() next steps, you just have to change $req->steps array.

extractFormInfo($req)

First authentication method called during authentication process. It must set $req->user that will be used by the userDB object to get user information.

authenticate($req)

Last method called during authentication process.

setAuthSessionInfo($req)

Method that must at least set $req->{sessionInfo}->{authenticationLevel} to an integer that indicates the strong of authentication.

Proposed levels:

1: low level
2: web form level
3: session based level (Kerberos for example)
5: strong authentication

authForce($req)

authLogout($req)

LOGGING

Logging is provided by $self->logger and $self->userLogger. The following rules must be applied:

logger->debug: technical debugging messages
logger->info: simple technical information
logger->notice: technical information that could interest administrators
logger->warn: technical warning
logger->error: error that must be reported to administrator
userLogger->info: simple information about user's action
userLogger->notice: information that may be registered (auth success,...)
userLogger->warn: bad action of a user (auth failure). Auth/Combination transform it to "info" when another authentication scheme is available
userLogger->error: bad action of a user that must be reported, (even if another backend is available with Combination)

AUTHORS

LemonLDAP::NG team http://lemonldap-ng.org/team

BUG REPORT

Use OW2 system to report bug or ask for features: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues

DOWNLOAD

Lemonldap::NG is available at http://forge.objectweb.org/project/showfiles.php?group_id=274

COPYRIGHT AND LICENSE

See COPYING file for details.

This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.