Class: Smart Authentication - provides a safe, in-memory object, to store the authentication data and to provide a standard way to work with authentication inside the Smart.Framework / modules.
It must be re-populated on each execution. This ensure using a good practice for Auth mechanisms.
It provides the core and only STATIC methods to integrate authentication with Smart.Framework
The very important security concerns regarding the authentication protection against forgery,
the mechanism implemented in this class will offer a very good protection by using CONSTANTS,
so after a successful or failed authentication, the page needs to refresh or load another page
in order to change authentication data.
This comes as a result of more than 15 years research over web and client/server technologies ...
The best practices are to never store Authentication objects in session because session can be forged.
To avoid such bad practices this object provide just STATIC methods !!
The best way is to store just the login ID and a safe password HASH (irreversible) in session
and re-check authentication each time when the page is loaded or to use the HTTP AUTH mechanism
to avoid store in session the username / password hash. Or this can be combined with cookies, but requires
much more atention to pay by avoiding session forgery or cookie leakage.
Session must be protected against forgery by implementing advanced detection mechanisms based on
IP address and the browser signature of the client. The Smart Session provides a good layer for this purpose.
Usage: static object: Class::method() - This class provides only STATIC methods
class Methods
public staticfunctionvalidate_cluster_id (
string$cluster
) {} :: BOOL
@return: {BOOLEAN} TRUE if the cluster ID is valid or FALSE if not
@param: {STRING} $cluster: The Auth Cluster ID ; empty or max length is 63, can contain just: _ a-z 0-9 -
Validate an Auth Cluster ID, as a sub-domain name for Auth
public staticfunctionget_cluster_id (
) {} :: STRING
@return: {STRING} `` empty string if Master, or sub-domain if Auth Cluster Slave, ex: `srv1`
Get the current (Server) Cluster ID, as a sub-domain name for Auth, from what is set into: SMART_FRAMEWORK_AUTH_CLUSTER_ID
public staticfunctionis_cluster_master_auth (
) {} :: BOOL
@return: {BOOLEAN} TRUE if the cluster ID is Empty (is Master) or FALSE if the cluster ID is non-empty, a slave node
Tests if current Auth Server is the Master Auth, used for clustered Authentication only
public staticfunctionis_cluster_current_workspace (
) {} :: BOOL
@return: {BOOLEAN} TRUE if the cluster ID is Empty (is Master) or FALSE if the cluster ID is non-empty, a slave node
Tests if current Auth Server is the Master Auth, used for clustered Authentication only
public staticfunctionvalidate_auth_ext_username (
string$auth_user_name
) {} :: BOOL
@return: {BOOLEAN} TRUE if the username is valid or FALSE if not
@param: {STRING} $auth_user_name: The Auth User Name to be validated ; max length is 25, can contain just: _ a-z 0-9 - . @
Validate an extended Auth User Name, ex: using email as username
@return: {BOOLEAN} TRUE if the username is valid or FALSE if not
@param: {STRING} $auth_user_name: The Auth User Name to be validated ; max length is 25, can contain just: a-z 0-9 .
@param: {BOOL} $check_reasonable: Check for reasonable length ; if FALSE, min length is 3 ; if TRUE, min length is 5
@return: {BOOLEAN} TRUE if the password is valid or FALSE if not
@param: {STRING} $auth_user_pass: The Auth Password (plain text) to be validated ; min length is 7 (8 if complexity is enabled) ; max length is 55
@param: {BOOL} $check_complexity: Check for password complexity ; if set to TRUE will allow just complex passwords
Validate an Auth Password
public staticfunctionpassword_hash_create (
string$plainpass
) {} :: STRING
@return: {STRING} will return an EMPTY string if the password is not valid or in case of failure ; if all OK will always return a 60 character string
@param: {STRING} $plainpass: The plain password ; min length is 7 ; max length is 55
Creates a SAFE Auth Password Hash, using algo=PASSWORD_BCRYPT (strong one-way hashing algorithm) ; cost=8 (fast, considered an acceptable baseline cost, with low hardware usage)
Password min length is 7 (8 if complexity is enabled) ; max length is 55 (as supported by PASSWORD_BCRYPT algo)
This will produce a standard crypt() compatible hash using the `$2y$` identifier
The salt is RANDOM and will be returned as standard being part of the hashed password
A random salt will always be used here, because:
- the salt option is deprecated since PHP 7.4 and removed since PHP 8.0
- it is now preferred to simply use a random salt that is generated by default
It will return a 60 character string if success or empty string in case of failure
public staticfunctionpassword_hash_check (
string$plainpass,
string$passhash
) {} :: BOOL
@return: {BOOL} Will return TRUE if password match or FALSE if not
@param: {STRING} $plainpass: The plain password ; min length is 7 ; max length is 55
@param: {STRING} $passhash: The password hash to be checked
Check (verify) a password hash provided by SmartAuth::password_hash_create()
It must use the same complexity check as it was used when password was hashed ; if not may return wrong results
public staticfunctionlock_auth_data (
) {} :: VOID
Lock the (in-memory) Auth Login Data
This should prevent running Set Auth Data after certain waypoint in code
@return: {BOOLEAN} TRUE if all data is OK, FALSE if not or try to reauthenticate under the same execution (which is not allowed ; must be just once per execution)
@param: {STRING} $y_realm: *OPTIONAL* The user Authentication Realm(s)
@param: {ENUM} $y_method: *OPTIONAL* The authentication method used, as description only: HTTP-BASIC / OTHER / ...
@param: {STRING} $y_cluster: Cluster ID or ''
@param: {INTEGER} $y_algo_pass: The Pass (Hash) Algo
@param: {STRING} $y_hashpass: The user login password hash or plain password ; for admin/task area it only supports the SmartHashCrypto::password() type pass hash (fixed, 128 characters long) and NOT the plain password ; for index area (and other areas) it may store either: the plain password (7..55 characters) or the pass hash (60..128 characters) ; is not recommended to store here the plain password ; however, it will be stored in memory as encrypted to avoid exposure
@param: {STRING} $y_user_name: The user username ; Mandatory ; must be valid safe username
@param: {STRING} $y_user_id: The user (login) ID ; can be the Username or Email (on backend this should be always set with the same value as Username)
@param: {ARRAY} $y_keys: *OPTIONAL* The user Private Key (will be stored in memory as encrypted to avoid exposure)
@param: {STRING} $y_user_email: *OPTIONAL* The user Email ; if email is used as login ID this may be redundant !
@param: {STRING} $y_user_fullname: *OPTIONAL* The user Full Name (First Name + Last Name)
@param: {ARRAY/STRING} $y_user_privileges_list: *OPTIONAL* The user Privileges List as string '<priv-a>,<priv-b>,...' or array ['priv-a','priv-b'] that list all the current user privileges ; a privilege key must have 3..28 characters and can contain only: a-z -
@param: {ARRAY/STRING} $y_user_restrictions_list: *OPTIONAL* The user Restrictions List as string '<restr-a>,<restr-b>,...' or array ['restr-a','restr-b'] that list all the current user restrictions ; a restriction key must have 3..28 characters and can contain only: a-z -
@param: {STRING} $y_user_quota: *OPTIONAL* The user (storage) Quota
@param: {ARRAY} $y_user_metadata: *OPTIONAL* The user metainfo, associative array with max 7 levels (sub-arrays must have no more than 6 sub-levels, can be either associative or not) ; Ex: [ 'some-key' => 101, 'another-key' => 'abc', '3rd-key' => true, '4th-key' => [0, 1, 2, 'a', 'b', 'c'], '5th-key' => [ 'x' => 'X', 'y' => 'y', 'z' => 'Z' ] ]
@param: {ARRAY} $y_workspaces: *OPTIONAL* The user workspaces defs with max 1 level
Set the (in-memory) Auth Login Data
It can be used just once per execution (session) as it stores the data using constants,
and the data cannot be changed after a successful or failed authentication has set.
public staticfunctionis_authenticated (
) {} :: BOOL
@return: {BOOLEAN} TRUE if current user is Logged-in, FALSE if not
Check the (in-memory) Auth Login Data if the current user is logged-in
public staticfunctionget_auth_data (
bool$y_skip_sensitive = false
) {} :: ARRAY
@return: {ARRAY} a complete array containing all the meta-data of the current auth user
Get the (in-memory) Auth Auth Data
public staticfunctionget_auth_area (
) {} :: STRING
@return: {STRING} The user auth area: [IDX] or [ADM/TSK]
Get the auth area method from (in-memory) Auth Login Data
public staticfunctionget_auth_method (
) {} :: STRING
@return: {STRING} The user login method
Get the auth user login method from (in-memory) Auth Login Data
public staticfunctionget_auth_realm (
) {} :: STRING
@return: {STRING} returns the current user auth realm or 'DEFAULT' if not set or empty
Get the auth realm of the current user stored in the (in-memory) Auth Login Data
public staticfunctionget_auth_cluster_id (
) {} :: STRING
@return: {STRING} returns the current user auth cluster ID or an empty string
Get the current user auth cluster ID from the (in-memory) Auth Login Data
public staticfunctionget_auth_id (
) {} :: STRING
@return: {STRING} if current user is Logged-in will get the user (login) ID which is mandatory, else an empty string
Get the current user auth ID from the (in-memory) Auth Login Data
public staticfunctionget_auth_username (
) {} :: STRING
@return: {STRING} returns the user login username or an empty string if not set
Get the current user auth username from the (in-memory) Auth Login Data
public staticfunctionget_auth_passhash (
) {} :: STRING
@return: {STRING} The plain password if was set or empty string
Get the auth (safe) stored password hash from (in-memory)
public staticfunctionget_auth_passalgo (
) {} :: INT
@return: {INT} The pass algo or -1 or -2 if invalid or does not exists
Get the pass algo
public staticfunctionget_auth_passalgo_name (
) {} :: STRING
@return: {STRING} The pass algo name or Unknown
Get the pass algo name
public staticfunctionget_user_email (
) {} :: STRING
@return: {STRING} returns the user login email or an empty string if not set
Get the current user email from the (in-memory) Auth Login Data
public staticfunctionget_user_fa2secret (
) {} :: STRING
@return: {STRING} The plain fa2-secret if was set and valid or empty string
Get the auth user (safe) stored 2fa-secret from (in-memory)
public staticfunctionget_user_seckey (
) {} :: STRING
@return: {STRING} The plain secret-key if was set and valid or empty string
Get the auth user (safe) stored secret-key from (in-memory)
public staticfunctionget_user_ssekey (
) {} :: STRING
@return: {STRING} The plain security-key if was set and valid or empty string
Get the auth user (safe) stored security-key from (in-memory)
public staticfunctionget_user_privkey (
) {} :: STRING
@return: {STRING} The plain private-key if was set and valid or empty string
Get the auth user (safe) stored private-key from (in-memory)
public staticfunctionget_user_pubkey (
) {} :: STRING
@return: {STRING} The plain public-key if was set and valid or empty string
Get the auth user stored public-key from (in-memory)
public staticfunctionget_user_cert (
) {} :: STRING
@return: {STRING} The plain sign-cert if was set and valid or empty string
Get the auth user stored sign-cert from (in-memory)
public staticfunctionget_user_infocert (
) {} :: STRING
@return: {STRING} The plain info-sign-cert if was set and valid or empty string
Get the auth user stored info-sign-cert from (in-memory)
public staticfunctionget_user_fullname (
) {} :: STRING
@return: {STRING} returns the user login full name or an empty string if not set
Get the current user Full Name (First + Last Name) from the (in-memory) Auth Login Data
public staticfunctionget_user_privileges (
) {} :: STRING
@return: {STRING} returns user login privileges as list-string like: '<privilege-one>,<privilege-two>,...' or an empty string if not set
Get the list of the current user privileges stored in the (in-memory) Auth Login Data
public staticfunctionget_user_arr_privileges (
) {} :: ARRAY
@return: {ARRAY} returns user login privileges as array like: [ '<privilege-one>', '<privilege-two>', ... ] or an empty array if not set
Get the list as Array of the current user privileges stored in the (in-memory) Auth Login Data
public staticfunctionget_user_restrictions (
) {} :: STRING
@return: {STRING} returns user login restrictions as list-string like: '<restriction-one>,<restriction-two>,...' or an empty string if not set
Get the list of the current user restrictions stored in the (in-memory) Auth Login Data
public staticfunctionget_user_arr_restrictions (
) {} :: ARRAY
@return: {STRING} returns user login restrictions as array like: [ '<restriction-one>', '<restriction-two>', ... ] or an empty string if not set
Get the list as Array of the current user restrictions stored in the (in-memory) Auth Login Data
@return: {BOOLEAN} TRUE if the current user have the tested restriction or FALSE if does not
Test if the current user restrictions contain the tested one using the (in-memory) Auth Login Data
public staticfunctionvalidate_privilege_or_restriction_key (
string$y_key_to_validate
) {} :: BOOL
@return: {BOOLEAN} TRUE if the current user have the tested Privilege/Restriction or FALSE if does not
Test if a Privilege/Restriction key is valid and contain only allowed chars
public staticfunctionget_user_quota (
) {} :: INT
@return: {INTEGER} returns the user (storage) quota
Get the current user quota stored in the (in-memory) Auth Login Data
public staticfunctionget_user_metadata (
) {} :: ARRAY
@return: {ARRAY} returns an array with all current user metadata
Get the current user metadata stored in the (in-memory) Auth Login Data
public staticfunctionget_user_workspaces (
) {} :: ARRAY
@return: {ARRAY} returns an array with all current user workspaces
Get the current user workspaces stored in the (in-memory) Auth Login Data
public staticfunctionget_user_prefixed_path_by_area_and_auth_id (
) {} :: STRING
@return: {STRING} empty string `` on error or unauthenticated ; or path, ex: `idx/ab/abc7.e8` | `adm/d7/8xyz.w0`
Get the current user path prefix by area and auth user ID
works just for already authenticated user
public staticfunctionget_user_prefixed_path_by_area_and_account_id (
string$area,
string$id
) {} :: STRING
@return: {STRING} empty string `` on error ; or path, ex: `idx/ab/abc7.e8` | `adm/d7/8xyz.w0`
@param: {STRING} $area: Area: `idx` | `adm`
@param: {STRING} $id: The user ID, must be valid as userName
Get the user path prefix by area and user ID
works outside of authentication, for management purposes
public staticfunctionencrypt_sensitive_data (
string$y_pkey,
string$y_secret
) {} :: STRING
@return: {STRING} returns a string with the safe encrypted privacy-key or empty string if was empty
@param: {STRING} $y_pkey: The private key to be safe encrypted
@param: {STRING} $y_secret: The encryption secret
Safe Encrypt a private key using a password, using Twofish+Blowfish CBC
The provided password have to be the same as the login password for the user is being used to avoid decryption of the key by other users
This is completely safe as long as the users login passwords are supposed to be stored as ireversible hashes (by default they are ... but with custom login implementations they can be or not, depending the developer's choice)
public staticfunctiondecrypt_sensitive_data (
string$y_pkey,
string$y_secret
) {} :: STRING
@return: {STRING} returns a string with the privacy-key (decrypted, if any, and if valid) which was supposed to be provided as encrypted
@param: {STRING} $y_pkey: The private key to be decrypted
@param: {STRING} $y_secret: The encryption secret
Decrypt a private key using a password, using Twofish+Blowfish CBC
The provided password have to be the same as the login password for the user is being used to avoid decryption of the key by other users
This is completely safe as long as the users login passwords are supposed to be stored as ireversible hashes (by default they are ... but with custom login implementations they can be or not, depending the developer's choice)
@return: {ARRAY} returns the associative/non-associative array of auth Privileges or Restrictions as [ 'key-a' => 'Key A', 'key-b' => 'Key B', ..., 'key-n' => 'Key N' ] or [ 'key-a', 'key-b', ..., 'key-n' ]
@param: {STRING/ARRAY} $y_list: List of Privileges or Restrictions as ARRAY [ 'key-a', 'key-b', ..., 'key-n' ] or STRING '<key-a>, <key-b>, ..., <key-n>'
@param: {BOOL} $nonassociative: Default is FALSE ; if TRUE will return non-associative (simple) ; if FALSE (default) will return associative
Build the associative Array of Auth Privileges or Restrictions
It must be re-populated on each execution. This ensure using a good practice for Auth mechanisms.
It provides the core and only STATIC methods to integrate authentication with Smart.Framework
The very important security concerns regarding the authentication protection against forgery,
the mechanism implemented in this class will offer a very good protection by using CONSTANTS,
so after a successful or failed authentication, the page needs to refresh or load another page
in order to change authentication data.
This comes as a result of more than 15 years research over web and client/server technologies ...
The best practices are to never store Authentication objects in session because session can be forged.
To avoid such bad practices this object provide just STATIC methods !!
The best way is to store just the login ID and a safe password HASH (irreversible) in session
and re-check authentication each time when the page is loaded or to use the HTTP AUTH mechanism
to avoid store in session the username / password hash. Or this can be combined with cookies, but requires
much more atention to pay by avoiding session forgery or cookie leakage.
Session must be protected against forgery by implementing advanced detection mechanisms based on
IP address and the browser signature of the client. The Smart Session provides a good layer for this purpose.