lemonldap-ng/doc/sources/admin/plugincustom.rst

257 lines
7.1 KiB
ReStructuredText

Write a custom plugin
=====================
Presentation
------------
Portal plugins let you customize LemonLDAP::NG's behavior.
Common use cases for plugins are:
* Looking up session information in an additional backend
* Implementing additional controls or steps during login
* Adjusting the behavior of SAML, OIDC or CAS protocols to work around application bugs
Creating a plugin can be as simple as writing a short Perl module file and
declaring it in your configuration. See below for an example.
Plugin API
----------
Authentication entry points
~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can now write a custom portal plugin that will hook in the
authentication process:
- ``beforeAuth``: method called before authentication process
- ``betweenAuthAndData``: method called after authentication and before
setting "sessionInfo" provisionning
- ``afterData``: method called after "sessionInfo" provisionning
- ``endAuth``: method called when session is validated (after cookie
build)
- ``authCancel``: method called when user click on "cancel" during auth
process
- ``forAuthUser``: method called for already authenticated users
- ``beforeLogout``: method called before logout
Generic entry points
~~~~~~~~~~~~~~~~~~~~
If you need to call a method just after any standard method in
authentication process, then use ``afterSub``, for example:
.. code-block:: perl
use constant afterSub => {
getUser => 'mysub',
};
sub mysub {
my ( $self ,$req ) = @_;
# Do something
return PE_OK;
}
If you need to call a method instead any standard method in
authentication process, then use ``aroundSub``, for example:
.. code-block:: perl
use constant aroundSub => {
getUser => 'mysub',
};
sub mysub {
my ( $self, $sub, $req ) = @_;
# Do something before
my $ret = $sub->($req);
# Do something after
return $ret;
}
Hooks
~~~~~
.. versionadded:: 2.0.10
Your plugin can also register itself to be called at some points of interest
within the main LemonLDAP::NG code.
.. toctree::
:maxdepth: 1
hooks
Routes
~~~~~~
The plugin can also define new routes and call actions on them.
See also ``Lemonldap::NG::Portal::Main::Plugin`` man page.
Configuration
~~~~~~~~~~~~~
The current LemonLDAP::NG configuration can be accessed in the ``$self->conf`` hash. This variable is only meant to be read. Don't try changing its content, or *Bad Things* may happen.
You can set your own parameters in ``General Parameters`` » ``Plugins`` » ``Custom plugins`` » ``Additional parameters``
and reach them through ``customPluginsParams``
.. code-block:: perl
sub my_function {
my ($self, $req) = @_;
# Get a standard LLNG option
my $llng_logo = $self->conf->{portalMainLogo};
# Get your custom LLNG option
my $myvar = $self->conf->{customPluginsParams}->{myvar};
}
Logs
~~~~
You can use the ``$self->logger`` and ``$self->userLogger`` objects to log information during your plugin execution. Use ``logger`` for technical logs and ``userLogger`` for accounting and tracability events.
.. code-block:: perl
sub my_function {
my ($self, $req) = @_;
$self->logger->debug("Debug message");
if (my_custom_test($req->user)) {
$self->userLogger->debug("User ". $req->user .
" is not allowed because XXX");
return PE_ERROR;
}
return PE_OK;
}
Remembering data
~~~~~~~~~~~~~~~~
In order to remember data between different steps, you can use the ``$req->data`` hash.
Data will not be remembered in between requests, only in between methods that process the same HTTP request.
History management
~~~~~~~~~~~~~~~~~~
Plugins may declare additional session fields to be stored in the :doc:`loginhistory`.
.. code:: perl
sub init {
my ($self) = @_;
$self->addSessionDataToRemember({
# This field will be hidden from the user
_language => '__hidden__',
# This field will be displayed on the portal. The column name
# is treated like a message and can be internationalized
authenticationLevel => "Human friendly column name",
});
return 1;
}
Column names can be translated by :ref:`overriding the corresponding message <intlmessages>`
Example
-------
Plugin Perl module
~~~~~~~~~~~~~~~~~~
This example creates a ``Lemonldap::NG::Portal::MyPlugin`` plugin that
showcases some features of the plugin system.
First, create a file to contain the plugin code ::
vi /usr/share/perl5/Lemonldap/NG/Portal/MyPlugin.pm
.. tip::
If you do not want to mix files from the distribution with
your own work, put your own code in
``/usr/local/lib/site_perl/Lemonldap/NG/Portal/MyPlugin.pm``.
Or you can use your own namespace such as ``ACME::Corp::MyPlugin``.
.. code-block:: perl
# The package name must match the file path
# This file must be in Lemonldap/NG/Portal/MyPlugin.pm
package Lemonldap::NG::Portal::MyPlugin;
use Mouse;
use Lemonldap::NG::Portal::Main::Constants;
extends 'Lemonldap::NG::Portal::Main::Plugin';
# Declare when LemonLDAP::NG must call your functions
use constant beforeAuth => 'verifyIP';
use constant hook => { passwordAfterChange => 'logPasswordChange' };
# This function will be called at the "beforeAuth" login step
sub verifyIP {
my ($self, $req) = @_;
return PE_ERROR if($req->address !~ /^10/);
return PE_OK;
}
# This function will be called when changing passwords
sub logPasswordChange {
my ( $self, $req, $user, $password, $old ) = @_;
$self->userLogger->info("Password changed for $user");
return PE_OK;
}
# You can define your custom initialization in the
# init method.
# Before LemonLDAP::NG 2.0.14, this function was mandatory
sub init {
my ($self) = @_;
# This is how you declare HTTP routes
$self->addUnauthRoute( mypath => 'hello', [ 'GET', 'PUT' ] );
$self->addAuthRoute( mypath => 'welcome', [ 'GET', 'PUT' ] );
# The function can return 0 to indicate failure
return 1;
}
# This method will be called to handle unauthenticated requests to /mypath
sub hello {
my ($self, $req) = @_;
...
return $self->p->sendJSONresponse($req, { hello => 1 });
}
# This method will be called to handle authenticated requests to /mypath
sub welcome {
my ($self, $req) = @_;
my $userid = $req->user;
$self->p->logger->debug("Call welcome for $userid");
...
return $self->p->sendHtml($req, 'template', params => { WELCOME => 1 });
}
# Your file must return 1, or Perl will complain.
1;
Enabling your plugin
~~~~~~~~~~~~~~~~~~~~
Declare the plugin in Manager, in General Parameters > Plugins > Custom
Plugins.
- Modules list: for example
``Lemonldap::NG::Portal::MyPlugin1, Lemonldap::NG::Portal::MyPlugin2``
- Additional parameters: parameters that will be available in
``customPluginsParams`` configuration key