NAME
WWW::Suffit::Plugin::SuffitAuth - The Suffit plugin for Suffit API authentication and authorization providing
SYNOPSIS
sub startup {
    my $self = shift->SUPER::startup();
    $self->plugin('SuffitAuth', {
        configsection    => 'SuffitAuth',
        expiration       => 3600, # 1h
        cache_expiration => 300, # 5m
        public_key_file  => 'suffitauth_pub.key',
        userfile_format  => 'user-%s.json',
    });
    # . . .
}
... configuration:
# SuffitAuth Client configuration
<SuffitAuth>
    ServerURL       https://api.example.com/api
    Insecure        on
    AuthScheme      Bearer
    Token           "eyJhb...1Okw"
    ConnectTimeout  60
    RequestTimeout  60
</SuffitAuth>
DESCRIPTION
The Suffit plugin for Suffit API authentication and authorization providing
OPTIONS
This plugin supports the following options
cache_expiration
cache_expiration => 300
cache_expiration => '5m'
This option sets default cache expiration time for keep user data in cache
Default: 300 (5 min)
configsection
configsection => 'suffitauth'
configsection => 'SuffitAuth'
This option sets a section name of the config file for define namespace of configuration directives for this plugin
Default: 'suffitauth'
expiration
expiration => 3600
expiration => '1h'
expiration => SESSION_EXPIRATION
This option performs set a default expiration time of session
Default: 3600 secs (1 hour)
See "SESSION_EXPIRATION" in WWW::Suffit::Const
public_key_file
public_key_file => 'auth_public.key'
This option sets default public key file location (relative to datadir)
Default: 'auth_public.key'
userfile_format
userfile_format => 'u.%s.json'
This option sets default format of userdata authorization filename
Default: 'u.%s.json'
HELPERS
This plugin provides the following helpers
suffitauth.authenticate
my $auth = $self->suffitauth->authenticate({
    address     => $self->remote_ip($self->app->trustedproxies),
    method      => $self->req->method, # 'ANY'
    base_url    => $self->base_url,
    referer     => $self->req->headers->header("Referer"),
    username    => $username,
    password    => $password,
    loginpage   => 'login', # -- To login-page!!
    expiration  => $remember ? SESSION_EXPIRE_MAX : SESSION_EXPIRATION,
    realm       => "Test zone", # Reserved. Now is not supported
    options     => {}, # Reserved. Now is not supported
});
if (my $err = $auth->get('/error')) {
    if (my $location = $auth->get('/location')) { # Redirect
        $self->flash(message => $err);
        $self->redirect_to($location); # 'login' -- To login-page!!
    } elsif ($auth->get('/status') >= 500) { # Fatal server errors
        $self->reply->error($auth->get('/status'), $auth->get('/code'), $err);
    } else { # User errors (show on login page)
        $self->stash(error => $err);
        return $self->render;
    }
    return;
}
This helper performs authentication backend subprocess and returns result object (Mojo::JSON::Pointer) that contains data structure:
{
    error       => '',          # Error message
    status      => 200,         # HTTP status code
    code        => 'E0000',     # The Suffit error code
    username    => $username,   # User name
    referer     => $referer,    # Referer
    loginpage   => $loginpage,  # Login page for redirects (location)
    location    => undef,       # Location URL for redirects
}
This method is typically called in a handler responsible for the authentication and authorization process, such as `login`. The call is typically made before a session is established, for eg.:
# Set session
$self->session(
        username => $username,
        remember => $remember ? 1 : 0,
        logged   => time,
        $remember ? (expiration => SESSION_EXPIRE_MAX) : (),
    );
$self->flash(message => 'Thanks for logging in.');
# Go to protected page (/root)
$self->redirect_to('root');
suffitauth.authorize
my $auth = $self->suffitauth->authorize({
    referer     => $referer,
    username    => $username,
    loginpage   => 'login', # -- To login-page!!
    options     => {}, # Reserved. Now is not supported
});
if (my $err = $auth->get('/error')) {
    if (my $location = $auth->get('/location')) {
        $self->flash(message => $err);
        $self->redirect_to($location); # 'login' -- To login-page!!
    } else {
        $self->reply->error($auth->get('/status'), $auth->get('/code'), $err);
    }
    return;
}
This helper performs authorization backend subprocess and returns result object (Mojo::JSON::Pointer) that contains data structure:
{
    error       => '',          # Error message
    status      => 200,         # HTTP status code
    code        => 'E0000',     # The Suffit error code
    username    => $username,   # User name
    referer     => $referer,    # Referer
    loginpage   => $loginpage,  # Login page for redirects (location)
    location    => undef,       # Location URL for redirects
    user    => {                # User data
        address     => "127.0.0.1", # User (client) IP address
        base        => "http://localhost:8080", # Base URL of request
        comment     => "No comments", # Comment
        email       => 'test@example.com', # Email address
        email_md5   => "a84450...366", # MD5 hash of email address
        method      => "ANY", # Current method of request
        name        => "Bob Smith", # Full user name
        path        => "/", # Current query-path of request
        role        => "Regular user", # User role
        status      => true, # User status in JSON::PP::Boolean notation
        uid         => 1, # User ID
        username    => $username, # User name
    },
}
The 'user' is structure that describes found user. For eg.:
{
    "address": "127.0.0.1",
    "base": "http://localhost:8473",
    "code": "E0000",
    "email": "foo@example.com",
    "email_md5": "b48def645758b95537d4424c84d1a9ff",
    "expires": 1700490101,
    "groups": [
        "wheel"
    ],
    "method": "ANY",
    "name": "Anon Anonymous",
    "path": "/",
    "role": "System Administratot",
    "status": true,
    "uid": 1,
    "username": "admin"
}
Typically, this method is called in the handler responsible for session accounting (logged_in). The call is accompanied by staking of the authorization data into the corresponding project templates, for example:
# Stash user data
$self->stash(
    username => $username,
    name     => $auth->get('/user/name') // 'Anonymous',
    email_md5=> $auth->get('/user/email_md5') // '',
    role     => $auth->get('/user/role') // 'User',
    user     => $auth->get('/user') || {},
);
suffitauth.client
my $client = $self->suffitauth->client;
Returns authorization client
suffitauth.init
my $init = $self->suffitauth->init;
This method returns the init object (Mojo::JSON::Pointer) that contains data of initialization:
{
    error       => '...',       # Error message
    status      => 500,         # HTTP status code
    code        => 'E7000',     # The Suffit error code
}
For example (in your controller):
# Check init status
my $init = $self->suffitauth->init;
if (my $err = $init->get('/error')) {
    $self->reply->error($init->get('/status'),
        $init->get('/code'), $err);
    return;
}
suffitauth.options
my $options = $self->suffitauth->options;
Returns authorization plugin options as hashref
suffitauth.unauthorize
my $auth = $self->suffitauth->unauthorize(username => $username);
if (my $err = $auth->get('/error')) {
    $self->reply->error($authdata->get('/status'), $authdata->get('/code'), $err);
}
This helper performs unauthorize process - remove userdata file from disk and returns result object (Mojo::JSON::Pointer) that contains data structure:
{
    error       => '',          # Error message
    status      => 200,         # HTTP status code
    code        => 'E0000',     # The Suffit error code
    username    => $username,   # User name
}
This method is typically called in the handler responsible for the logout process. The call usually occurs before the redirect to the `login` page, for example:
# Remove session
$self->session(expires => 1);
# Unauthorize
if (my $username = $self->session('username')) {
    my $authdata = $self->suffitauth->unauthorize(username => $username);
    if (my $err = $authdata->get('/error')) {
        $self->reply->error($authdata->get('/status'), $authdata->get('/code'), $err);
    }
}
# To login-page!
$self->redirect_to('login');
METHODS
Internal methods
register
This method register the plugin and helpers in Mojolicious application
ERROR CODES
- E0xxx -- General errors
 - 
E01xx, E02xx, E03xx, E04xx and E05xx are reserved as HTTP errors
E0000 Ok E0100 Continue E0200 OK E0300 Multiple Choices E0400 Bad Request E0500 Internal Server Error - E1xxx -- API errors
 - 
See WWW::Suffit::API
 - E2xxx -- Database errors
 - 
See WWW::Suffit::API
 - E7xxx -- SuffitAuth (application) errors
 - 
Auth: E70xx
E7000 [403] Access denied E7001 [400] Incorrect username E7002 [503] Can't connect to authorization server E7003 [500] Can't get public key from authorization server E7004 [500] Can't save public key file %s E7005 [*] Authentication error E7006 [*] Authorization error E7007 [500] Can't save file <USERNAME>.json E7008 [500] File <USERNAME>.json not found or incorrect E7009 [400] Incorrect username (while authorize) E7010 [400] Incorrect username (while unauthorize)* -- this code defines on server side
 
SEE ALSO
Mojolicious, WWW::Suffit::Client::V1, WWW::Suffit::Server, bundled examples
AUTHOR
Serż Minus (Sergey Lepenkov) https://www.serzik.com <abalama@cpan.org>
COPYRIGHT
Copyright (C) 1998-2025 D&D Corporation. All Rights Reserved
LICENSE
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
See LICENSE file and https://dev.perl.org/licenses/