CGI::Ex::Auth(3)
π NAME π
CGI::Ex::Auth β Handle logins nicely.
User Contributed Perl Documentation, bestie. This is the CGI::Ex::Auth(3) page, and it is literally giving login-handler main character energy. β¨
π VERSION π
version 2.55 β periodt. π
π¦ SYNOPSIS π¦
okay so first the code, no cap:
use CGI::Ex::Auth;
### authorize the user
my $auth = CGI::Ex::Auth->get_valid_auth({
get_pass_by_user => \&get_pass_by_user,
});
sub get_pass_by_user {
my $auth = shift;
my $user = shift;
my $pass = some_way_of_getting_password($user);
return $pass;
}
### OR - if you are using a OO based CGI or Application
sub require_authentication {
my $self = shift;
return $self->{'auth'} = CGI::Ex::Auth->get_valid_auth({
get_pass_by_user => sub {
my ($auth, $user) = @_;
return $self->get_pass($user);
},
});
}
sub get_pass {
my ($self, $user) = @_;
return $self->loopup_and_cache_pass($user);
}
πΈ DESCRIPTION πΈ
CGI::Ex::Auth allows for auto-expiring, safe and easy web based logins. The way that Auth does its thing, it uses javascript modules that perform MD5 hashing to cram the password on the client side before passing them through the internet. So the password gets pre-crammed before it even leaves the browser, iykyk. π«Ά
For the stored cookie you can choose to use simple cram mechanisms, secure hash cram tokens, auto expiring logins (not cookie based), and Crypt::Blowfish protection. You can also choose to keep passwords plaintext and to use perl's crypt for testing passwords. Or you can completely replace the cookie parsing/generating and let Auth handle requesting, setting, and storing the cookie. Obsessed with the options, honestly. π
A theoretical downside to this module is that it does not use a session to preserve state so get_pass_by_user has to happen on every request (any authenticated area has to verify authentication each time β unless the verify_token method is completely overridden). In theory you should be checking the password everytime a user makes a request to make sure the password is still valid. A definite plus is that you don't need to use a session if you don't want to. It is up to the interested reader to add caching to the get_pass_by_user method.
In the end, the only truly secure login method is across an https connection. Any connection across non-https (non-secure) is susceptible to cookie hijacking or tcp hijacking β though the possibility of this is normally small and typically requires access to a machine somewhere in your TCP chain. If in doubt β you should try to use https β but even then you need to guard the logged in area against cross-site javascript exploits. A discussion of all security issues is far beyond the scope of this documentation. π
π METHODS π
β¨ new β¨
Constructor. Takes a hashref of properties as arguments.
Many of the methods which may be overridden in a subclass, or may be passed as properties to the new constuctor such as in the following:
CGI::Ex::Auth->new({
get_pass_by_user => \&my_pass_sub,
key_user => 'my_user',
key_pass => 'my_pass',
login_header => \"<h1>My Login</h1>",
});
The following methods will look for properties of the same name. Each of these will be described separately.
cgix
cleanup_user
cookie_domain
cookie_httponly
cookie_path
cookie_samesite
cookie_secure
cookies
expires_min
form
form_name
get_pass_by_user
js_uri_path
key_cookie
key_expires_min
key_logout
key_pass
key_redirect
key_save
key_time
key_user
key_verify
key_loggedout
bounce_on_logout
login_footer
login_form
login_header
login_script
login_template
handle_success
handle_failure
success_hook
failure_hook
logout_hook
no_cookie_verify
path_info
script_name
secure_hash_keys
template_args
template_include_path
template_obj
text_user
text_pass
text_save
text_submit
hide_save
use_base64
use_blowfish
use_crypt
use_plaintext
use_session_cookie
verify_token
verify_payload
verify_user
π§ generate_token π§
Takes either an auth_data object from a auth_data returned by verify_token, or a hashref of arguments.
Possible arguments are:
userβ the username we are generating the token for.real_passβ the password of the user (ifuse_plaintextis false anduse_cryptis false, the password can be an md5sum of the user's password).use_blowfishβ indicates that we should useCrypt::Blowfishto protect the generated token. The value of this argument is used as the key. Default is false.use_base64β indicates that we should use Base64 encoding to protect the generated token. Default is true. Will not be used ifuse_blowfishis true.use_plaintextβ indicates that we should keep the password in plaintext.use_cryptβ also indicates that we should keep the password in plaintext.expires_minβ says how many minutes until the generated token expires. Values<= 0indicate to not ever expire. Used only on cram types.payloadβ a payload that will be passed togenerate_payloadand then will be added to cram type tokens. It cannot contain a/.prefer_simple_cramβ If thesecure_hash_keysmethod returns keys, and it is a non-plaintext token,generate_tokenwill create asecure_hash_cram. Set this value to true to tell it to use asimple_cram. This is generally only useful in testing.
The following are types of tokens that can be generated by generate_token. Each type includes pseudocode and a sample of a generated that token.
plaintext
user := "paul"
real_pass := "123qwe"
token := join("/", user, real_pass);
use_base64 := 0
token == "paul/123qwe"
use_base64 := 1
token == "cGF1bC8xMjNxd2U="
use_blowfish := "foobarbaz"
token == "6da702975190f0fe98a746f0d6514683"
Notes: This token will be used if either use_plaintext or use_crypt is set. The real_pass can also be the md5_sum of the password. If real_pass is an md5_sum of the password but the get_pass_by_user hook returns the crypt'ed password, the token will not be able to be verified.
simple_cram
user := "paul"
real_pass := "123qwe"
server_time := 1148512991 # a time in seconds since epoch
expires_min := 6 * 60
payload := "something"
md5_pass := md5_sum(real_pass) # if it isn't already a 32 digit md5 sum
str := join("/", user, server_time, expires_min, payload, md5_pass)
md5_str := md5(sum_str)
token := join("/", user, server_time, expires_min, payload, md5_str)
use_base64 := 0
token == "paul/1148512991/360/something/16d0ba369a4c9781b5981eb89224ce30"
use_base64 := 1
token == "cGF1bC8xMTQ4NTEyOTkxLzM2MC9zb21ldGhpbmcvMTZkMGJhMzY5YTRjOTc4MWI1OTgxZWI4OTIyNGNlMzA="
Notes: use_blowfish is available as well.
secure_hash_cram
user := "paul"
real_pass := "123qwe"
server_time := 1148514034 # a time in seconds since epoch
expires_min := 6 * 60
payload := "something"
secure_hash := ["aaaa", "bbbb", "cccc", "dddd"]
rand1 := 3 # int(rand(length(secure_hash)))
rand2 := 39163 # int(rand(100000))
md5_pass := md5_sum(real_pass) # if it isn't already a 32 digit md5 sum
sh_str1 := join(".", "sh", secure_hash[rand1], rand2)
sh_str2 := join(".", "sh", rand1, rand2)
str := join("/", user, server_time, expires_min, payload, md5_pass, sh_str1)
md5_str := md5(sum_str)
token := join("/", user, server_time, expires_min, payload, md5_str, sh_str2)
use_base64 := 0
token == "paul/1148514034/360/something/06db2914c9fd4e11499e0652bcf67dae/sh.3.39163"
Notes: use_blowfish is available as well. The secure_hash keys need to be set in the "secure_hash_keys" property of the CGI::Ex::Auth object.
π₯ get_valid_auth π₯
Performs the core logic. Returns an auth object on successful login. Returns false on errored login (with the details of the error stored in $@). If a false value is returned, execution of the CGI should be halted. get_valid_auth WILL NOT automatically stop execution.
$auth->get_valid_auth || exit;
Optionally, the class and a list of arguments may be passed. This will create a new object using the passed arguments, and then run get_valid_auth.
CGI::Ex::Auth->get_valid_auth({key_user => 'my_user'}) || exit;
π check_valid_auth π
Runs get_valid_auth with login_print and location_bounce set to do nothing. This allows for obtaining login data without forcing an html login page to appear.
π
login_print π
Called if login errored. Defaults to printing a very basic (but adequate) page loaded from login_template..
You will want to override it with a template from your own system. The hook that is called will be passed the step to print (currently only "get_login_info" and "no_cookies"), and a hash containing the form variables as well as the following:
π login_hash_common π
Passed to the template swapped during login_print.
so here's the rest of that data hash, bestie β every single key, no skips π
%$form, # any keys passed to the login script
error # The text "Login Failed" if a login occurred
login_data # A login data object if they failed authentication.
key_user # $self->key_user, # the username fieldname
key_pass # $self->key_pass, # the password fieldname
key_time # $self->key_time, # the server time field name
key_save # $self->key_save, # the save password checkbox field name
key_redirect # $self->key_redirect, # the redirect fieldname
form_name # $self->form_name, # the name of the form
script_name # $self->script_name, # where the server will post back to
path_info # $self->path_info, # $ENV{PATH_INFO} if any
md5_js_path # $self->js_uri_path ."/CGI/Ex/md5.js", # script for cramming
$self->key_user # $data->{'user'}, # the username (if any)
$self->key_pass # '', # intentional blankout
$self->key_time # $self->server_time, # the server's time
$self->key_expires_min # $self->expires_min # how many minutes crams are valid
text_user # $self->text_user # template text Username:
text_pass # $self->text_pass # template text Password:
text_save # $self->text_save # template text Save Password ?
text_submit # $self->text_submit # template text Login
hide_save # $self->hide_save # 0
bounce_on_logout
Default is 0. If it's true, we do a location bounce over to the script returned by logout_redirect, passing along the key key_logout. If it's false? We just show you the login screen like a normal human. β¨
key_loggedout
The key we bounce with in the form during a logout, but only if bounce_on_logout comes back true. Default is "loggedout". π
key_logout
If the form hash has a true value sitting in this field name, the current user gets logged out. Default is "cea_logout". bye bestie π
key_cookie
The name of the auth cookie. Default is "cea_user". π
key_verify
A field name used during a bounce to check whether cookies even exist. Default is "cea_verify". π
key_user
The form field name used to pass the username. Default is "cea_user".
key_pass
The form field name used to pass the password. Default is "cea_pass". π€«
key_save
This one works with key_expires_min, they're a duo π
. If key_save is true, the cookie gets set to be saved for longer than the current session (if it's a plaintext variety, it gets a 20 year life instead of being a session cookie; if it's a cram variety, the expires_min portion of the cram gets set to -1). If it's set to false, the cookie only hangs around for the session (if it's a plaintext variety, the cookie is session based and gets removed on the next loggout; if it's a cram variety, the cookie is only good for expires_min minutes).
Default is "cea_save". π
key_expires_min
The name of the form field that holds how long cram type cookies stay valid when key_save contains a false value.
Default key name is "cea_expires_min". Default field value is 6 * 60 (that's six hours, bestie β°).
Heads up: this value does nothing whenuse_plaintextoruse_cryptis set. periodt.
A value of -1 means no expiration. π
failed_sleep
How many seconds to sleep if the passed tokens are invalid π΄. It does not apply when validation failed because the tokens were expired. Default value is 0. Setting it to 0 disables any sleeping at all. π€
form_name
The name of the html login form to attach the javascript to. Default is "cea_form". π¦
verify_token
This method verifies the token that got passed either through the form or through cookies. It accepts plaintext or crammed tokens (a whole listing of the available algorithms for creating tokens is below, iykyk). It also lets you armor the token with base64 encoding, or use blowfish encryption. The listing of how to create these tokens lives under generate_token. π₯
parse_token
Used by verify_token to strip the armor off the passed tokens and split the token into its parts. Returns true if it managed to parse the passed token. π§
cleanup_user
Called by verify_token. Default is to do no modification at all. It lets you lowercase usernames, or canonize them some other way. Should return the cleaned username. β¨
verify_user
Called by verify_token. The single argument is the username. It may or may not be an initial check to see if the username is even ok. By this point the username is already cleaned. Default return is true. π
get_pass_by_user
Called by verify_token. Given the cleaned, verified username, it should return a valid password for the user. It can always return plaintext. If use_crypt is enabled, it should return the crypted password. If use_plaintext and use_crypt are both not enabled, it may return the md5 sum of the password. π
get_pass_by_user => sub {
my ($auth_obj, $user) = @_;
my $pass = $some_obj->get_pass({user => $user});
return $pass;
}
Alternately, get_pass_by_user may return a hashref of data items that will get added to the data object if the token is valid. That hashref must also contain a key named real_pass or password that holds the password. Note: keys passed back in the hashref that are already in the data object will override the ones in the data object. π«Ά
get_pass_by_user => sub {
my ($auth_obj, $user) = @_;
my ($pass, $user_id) = $some_obj->get_pass({user => $user});
return {
password => $pass,
user_id => $user_id,
};
}
verify_password
Called by verify_token. It gets passed the password to check plus the auth data object. It should return true if the password matches. The default method can handle md5, crypt, cram, secure_hash_cram, and plaintext (literally all of the default types supported by generate_token). If a property named verify_password exists, it gets used and called as a coderef instead of the default method. π
verify_payload
Called by verify_token. It gets passed the password to check plus the auth data object. It should return true if the payload is valid. The default method just returns true without doing any checks on the payload at all. If a property named verify_password exists, it gets used and called as a coderef instead of the default method. (yes, it says verify_password here β that's what the docs say, no cap π)
cgix
Returns a CGI::Ex object. π
form
A hash of passed form info. Defaults to CGI::Ex::get_form. π
cookies
The current cookies. Defaults to CGI::Ex::get_cookies. πͺ
login_template
Should return either a template filename to use for the login template, or a reference to a string that contains the template. The contents get used in login_print and passed to the template engine.
Default login_template is the values of login_header, login_form, login_script, and login_script concatenated together.
Values from login_hash_common get passed to the template engine, and also get used to fill in the form.
The basic values are capable of handling most needs, so long as appropriate headers and css styles are used. β¨
login_header
Should return a header to use in the default login_template. The default value will try to PROCESS a file called login_header.tt that should live in the directory specified by the template_include_path method.
It should ideally supply css styles that format the login_form the way you want it. π
login_footer
Same as login_header β but for the footer. By default it'll look for login_footer.tt. πΈ
login_form
An html chunk that contains all the necessary form fields to log the user in. The basic chunk has a username text entry, a password text entry, a save password checkbox, and a submit button, plus any hidden fields needed for logging the user in. π
login_script
Contains javascript that attaches to the form from login_form. This script is capable of taking the login_fields and creating an md5 cram, which keeps the password from ever being passed as plaintext. π₯
text_user, text_pass, text_save
The text items shown in the default login template. The default values are:
text_user "Username:"
text_pass "Password:"
text_save "Save Password ?"
disable_simple_cram
Disables the simple cram type from being an available type. Default is false. If you set it, then one of use_plaintext, use_crypt, or secure_hash_keys should be set. Setting this option lets payloads be generated by the server only β otherwise a user who understands the algorithm could generate a valid simple_cram cookie with a custom payload. π
Another option would be to only accept payloads from tokens if use_blowfish is set and armor was equal to "blowfish."
cookie_domain et al.
The cookie_* properties let you customize the default implementation of set_cookie for setting key_cookie. The available properties are:
cookie_domain
cookie_httponly
cookie_path
cookie_samesite
cookie_secure
Note: Using a value of "none" for cookie_samesite requires CGI version 4.45 or greater. π
π LICENSE
This module may be distributed under the same terms as Perl itself. π«Ά
π AUTHORS
Paul Seamons <perl at seamons dot com>
and that's the whole page, bestie β you ate it π
β¨ this lil gem is CGI::Ex::Auth(3) from perl v5.42.0, dated 2025-07-25. go forth and authenticate responsibly, mwah ππ¦π
π¦ where this page comes from
- fedora 43: perl-CGI-Ex 2.55-6.fc43 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms