NAME
Concierge::Auth::Pwd - Password-file Concierge::Auth backend using Crypt::Passphrase
VERSION
v0.5.0
SYNOPSIS
use Concierge::Auth::Pwd;
# Initialize with a password file
my $auth = Concierge::Auth::Pwd->new( file => '/path/to/auth.pwd' );
# Or without a file (generators and utilities only)
my $auth = Concierge::Auth::Pwd->new( no_file => 1 );
# --- Concierge::Auth::Base contract methods ---
my $result = $auth->enroll('alice', 'secret123');
my $result = $auth->authenticate('alice', 'secret123');
my $result = $auth->is_id_known('alice');
my $result = $auth->change_credentials('alice', 'newsecret456');
my $result = $auth->revoke('alice');
# --- Backend-specific methods (password-file only) ---
my ($ok, $msg) = $auth->setFile('/path/to/other.pwd');
my $hash = $auth->encryptPwd('secret123');
# Generate tokens and random values (inherited from Concierge::Auth::Base)
my ($uuid, $msg) = $auth->gen_uuid(); # v4 UUID
my ($id, $msg) = $auth->gen_random_id(); # 40-char hex ID
my ($token, $msg) = $auth->gen_random_token(32);
my ($string, $msg) = $auth->gen_random_string(16);
my ($phrase, $msg) = $auth->gen_word_phrase(4, 4, 7, '-');
DESCRIPTION
Concierge::Auth::Pwd is the built-in password-file backend for Concierge::Auth. It implements the Concierge::Auth::Base contract (authenticate, is_id_known, enroll, change_credentials, revoke) on top of a password store backed by Crypt::Passphrase with Argon2 encoding and Bcrypt validation for legacy password migration. Passwords are stored in a tab-separated file with file-locking for concurrent access.
Token and random value generation (gen_uuid, gen_random_id, gen_random_token, gen_random_string, gen_word_phrase) is not implemented by this module -- it is inherited from Concierge::Auth::Base's default implementations, which delegate to Concierge::Auth::Generators (using Crypt::PRNG for cryptographically secure random output). See "The Generators Guarantee" in Concierge::Auth::Base.
Concierge::Auth::Pwd is one backend of Concierge::Auth, the authentication component of the Concierge suite, alongside Concierge::Sessions (session management) and Concierge::Users (user data storage). It can also be used standalone.
Two Method Layers
This module itself defines two layers of methods:
Contract methods (
authenticate,is_id_known,enroll,change_credentials,revoke) -- the interface defined by Concierge::Auth::Base. These are whatConciergecalls, and every Concierge::Auth backend (this one, or an alternative such as an LDAP-backed backend) implements them. Password-file I/O and validation are written directly inline in these methods -- there are no intermediate backend-primitive methods to hop through. They return the{ success =1|0, ... }> hashref convention used throughout the rest of the Concierge suite.validatePwdis kept as a small shared helper since bothenrollandchange_credentialsneed it; it also returns the hashref convention.Backend-specific methods (file-management and encryption) -- specific to how this backend manages its password file, independent of the contract logic above. Other backends are not expected to implement these, and application code that wants to remain backend-agnostic should prefer the contract methods. These retain the original wantarray-sensitive
(bool, message)dual-return convention:$valuein scalar context,($value, $message)in list context.
A third set of methods -- token/random value generation -- is available on every instance but is not defined in this module at all; see "DESCRIPTION" above.
CONSTRUCTOR
new
my $auth = Concierge::Auth::Pwd->new(%args);
Creates a new backend object. The Crypt::Passphrase encoder (Argon2) is initialized immediately.
Arguments:
file-- path to the password file. Created if it does not exist. File permissions are set to0600. Croaks if the file cannot be opened or created.no_file-- if true, skip file setup. The object can still generate tokens and hash passwords, but cannot perform ID or password checks.
If neither file nor no_file is provided, the object is still created (with a warning), but file-dependent methods will fail.
CONTRACT METHODS
authenticate
my $result = $auth->authenticate($user_id, $password);
Verifies that $password is valid for $user_id. Pure check, no side effects. Malformed/empty IDs or passwords are rejected without a file scan; a wrong-length password otherwise simply fails to match the stored hash, so no separate format check is applied to it here.
Returns { success = 1 }> or { success = 0, message => '...' }>.
is_id_known
my $result = $auth->is_id_known($user_id);
Checks whether $user_id has a record in the password file. Empty, malformed, or missing IDs and missing files are all simply "not known" for this backend -- there is no failure branch short of a genuine I/O error on a file that does exist.
Returns { success = 1, known => 1|0 }>.
enroll
my $result = $auth->enroll($user_id, $password);
Creates a new password record for $user_id. $user_id must meet the length and character constraints (this is the only contract method that enforces ID format policy, since it's the only one establishing a new ID). Fails if the ID already exists (use change_credentials to change an existing password).
Returns { success = 1, user_id => $user_id, status => 'created' }> or { success = 0, message => '...' }>.
change_credentials
my $result = $auth->change_credentials($user_id, $new_password);
Replaces the stored password hash for an existing $user_id. Fails if the ID is not found.
Returns { success = 1, user_id => $user_id }> or { success = 0, message => '...' }>.
revoke
my $result = $auth->revoke($user_id);
Removes the password record for $user_id. Fails if the ID is not found. No ID format policy check is applied -- a malformed-but-nonempty ID simply fails to match any record on file.
Returns { success = 1, user_id => $user_id }> or { success = 0, message => '...' }>.
validatePwd
my $result = $auth->validatePwd($password);
Checks whether $password meets the length constraints. Shared by enroll and change_credentials, both of which establish a new credential value; not used by authenticate, since a wrong-length submitted password simply fails to match the stored hash.
Returns { success = 1 }> or { success = 0, message => '...' }>.
BACKEND-SPECIFIC METHODS
File Management
setFile
my ($ok, $msg) = $auth->setFile($path);
Sets (or changes) the password file path. Creates the file if it does not exist and sets permissions to 0600.
rmFile
my ($file, $msg) = $auth->rmFile();
Deletes the password file and clears the stored path. In list context, returns the deleted file path on success.
clearFile
my ($ok, $msg) = $auth->clearFile();
Removes and re-creates the password file, effectively deleting all records.
pfile
my ($file, $msg) = $auth->pfile();
Returns the path to the configured password file.
Utilities
encryptPwd
my $hash = $auth->encryptPwd($password);
Returns the Argon2 hash of $password. Validates password constraints first.
Token and Value Generation
gen_uuid, gen_random_id, gen_random_token, gen_random_string, and gen_word_phrase are available on every instance but are not implemented in this module -- they are inherited default implementations from Concierge::Auth::Base, which delegate to Concierge::Auth::Generators and use its dual-return convention: ($value, $message) in list context, $value in scalar context. See "GENERATOR METHODS" in Concierge::Auth::Base for the full list and "The Generators Guarantee" in Concierge::Auth::Base for why this backend does not need to (but could) override them.
SEE ALSO
Concierge::Auth::Base -- the backend contract this module implements
Concierge::Auth::Generators -- functional interface to the generators
Concierge::Sessions, Concierge::Users -- companion Concierge components
Crypt::Passphrase, Crypt::PRNG
AUTHOR
Bruce Van Allen <bva@cruzio.com>
LICENSE
This module is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.