, (*1)
Identity Authentication Tracking extension for Yii2
This extension provides identity authentication logging and tracking mechanism, which can be used
for 'brute-force' attack protection., (*2)
For license information check the LICENSE-file., (*3)
, (*4)
Installation
The preferred way to install this extension is through composer., (*5)
Either run, (*6)
php composer.phar require --prefer-dist yii2tech/authlog
or add, (*7)
"yii2tech/authlog": "*"
to the require section of your composer.json., (*8)
Usage
This extension provides identity authentication logging and tracking mechanism, which can be used
for 'brute-force' attack protection., (*9)
Extension works through the ActiveRecord entity for the authentication attempt log.
The database migration for such entity creation can be following:, (*10)
$this->createTable('UserAuthLog', [
'id' => $this->primaryKey(),
'userId' => $this->integer(),
'date' => $this->integer(),
'cookieBased' => $this->boolean(),
'duration' => $this->integer(),
'error' => $this->string(),
'ip' => $this->string(),
'host' => $this->string(),
'url' => $this->string(),
'userAgent' => $this->string(),
]);
ActiveRecord model, which implements [[\yii\web\IdentityInterface]] should declare a 'has many' relation to this entity.
The logging mechanism is provided via [[\yii2tech\authlog\AuthLogIdentityBehavior]] behavior, which should be as well
attached to the identity class. For example:, (*11)
use Yii;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
use yii2tech\authlog\AuthLogIdentityBehavior;
class User extends ActiveRecord implements IdentityInterface
{
public function behaviors()
{
return [
'authLog' => [
'class' => AuthLogIdentityBehavior::className(),
'authLogRelation' => 'authLogs',
'defaultAuthLogData' => function ($model) {
return [
'ip' => Yii::$app->request->getUserIP(),
'host' => @gethostbyaddr(Yii::$app->request->getUserIP()),
'url' => Yii::$app->request->getAbsoluteUrl(),
'userAgent' => Yii::$app->request->getUserAgent(),
];
},
],
];
}
public function getAuthLogs()
{
return $this->hasMany(UserAuthLog::className(), ['userId' => 'id']);
}
// ...
}
Note: because [[\yii2tech\authlog\AuthLogIdentityBehavior]] works through ActiveRecord the auth log storage can be
any one, which have ActiveRecord layer implemented, such as Redis, MongoDB etc., (*12)
Being attached [[\yii2tech\authlog\AuthLogIdentityBehavior]] provides basic auth logging and statistic methods:, (*13)
-
logAuth()
writes auth log entry
-
logAuthError()
writes auth log error entry
-
getLastSuccessfulAuthLog()
returns last successful auth log entry
-
getPreLastSuccessfulAuthLog()
returns pre-last successful auth log entry
-
getLastLoginDate()
returns last successful login date
-
getPreLastLoginDate()
returns pre-last successful login date
-
hasFailedLoginSequence()
checks if there is sequence of failed login attempts of request length starting from now
Refer to [[\yii2tech\authlog\AuthLogIdentityBehavior]] for details about configuration and available methods., (*14)
Keep in mind that [[\yii2tech\authlog\AuthLogIdentityBehavior]] does NOT log authentication attempts automatically.
You'll have to invoke logging methods manually in a proper place to do so. However this extension provides other
tools, which cover this task., (*15)
Automatic authentication logging
Although [[\yii2tech\authlog\AuthLogIdentityBehavior]] provides the basis for the auth logging, it does not
log anything automatically. Automatic logging of the successful authentication attempts are provided
via [[\yii2tech\authlog\AuthLogWebUserBehavior]] behavior.
[[\yii2tech\authlog\AuthLogWebUserBehavior]] should be attached to the 'user' application component (instance
of [[\yii\web\User]]). This could be done at the application configuration:, (*16)
return [
'components' => [
'user' => [
'identityClass' => 'app\models\User',
'loginUrl' => ['site/login'],
'as authLog' => [
'class' => 'yii2tech\authlog\AuthLogWebUserBehavior'
],
],
// ...
],
// ...
];
[[\yii2tech\authlog\AuthLogWebUserBehavior]] relies identity class has a [[\yii2tech\authlog\AuthLogIdentityBehavior]] attached
and writes auth log on any successful login made through owner [[\yii\web\User]] component, including the ones
based on cookie. However, this behavior can not log any failed authentication attempt, which should be done
elsewhere like login form., (*17)
Logging authentication failures
Logging authentication failures is specific to the authentication method used by application. Thus you are
responsible of its performing by yourself., (*18)
Most common authentication method is usage of username/password pair, which is asked via login web form.
In such workflow authentication failure should be written on invalid password entered.
This extension provides [[\yii2tech\authlog\AuthLogLoginFormBehavior]] behavior, which can be attached to the
login form model, providing authentication failures logging feature. For example:, (*19)
use app\models\User;
use yii2tech\authlog\AuthLogLoginFormBehavior;
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
public function behaviors()
{
return [
'authLog' => [
'class' => AuthLogLoginFormBehavior::className(),
'findIdentity' => 'findIdentity',
],
];
}
public function findIdentity()
{
return User::findByUsername($this->username);
}
// ...
}
[[\yii2tech\authlog\AuthLogLoginFormBehavior]] automatically logs failure authentication attempt on owner
validation in case identity is found and there is any error on [[\yii2tech\authlog\AuthLogLoginFormBehavior::$verifyIdentityAttributes]]., (*20)
"Brute force" protection
In addition to simple logging [[\yii2tech\authlog\AuthLogLoginFormBehavior]] provide built-in "brute force" attack
protection mechanism, which have 2 levels:, (*21)
- require robot verification (CAPTCHA) after [[\yii2tech\authlog\AuthLogLoginFormBehavior::$verifyRobotFailedLoginSequence]] sequence login failures
- deactivation of the identity record after [[\yii2tech\authlog\AuthLogLoginFormBehavior::$deactivateFailedLoginSequence]] sequence login failures
For example:, (*22)
use app\models\User;
use yii2tech\authlog\AuthLogLoginFormBehavior;
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
public $verifyCode;
public function behaviors()
{
return [
'authLog' => [
'class' => AuthLogLoginFormBehavior::className(),
'findIdentity' => 'findIdentity',
'verifyRobotAttribute' => 'verifyCode',
'deactivateIdentity' => function ($identity) {
return $this->updateAttributes(['statusId' => User::STATUS_SUSPENDED]);
},
],
];
}
public function rules()
{
return [
[['username', 'password'], 'required'],
['rememberMe', 'boolean'],
['password', 'validatePassword'],
['verifyCode', 'safe'],
];
}
public function findIdentity()
{
return User::findByUsername($this->username);
}
// ...
}
Robot verification requires extra processing at the view layer, which should render CAPTCHA only if it is necessary:, (*23)
'login-form']); ?>
= $form->field($model, 'username') ?>
= $form->field($model, 'password')->passwordInput() ?>
user->enableAutoLogin) : ?>
<?= $form->field($model, 'rememberMe')->checkbox() ?>
isVerifyRobotRequired) : ?>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
'template' => '{image}{input}',
]) ?>
= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
Heads up! Although [[\yii2tech\authlog\AuthLogLoginFormBehavior]] is supposed to cover most common web login
form workflow, do not limit yourself with it. Be ready to create your own implementation of the feature., (*24)
Garbage Collection
Logging every authentication attempt for every user in the system may cause log storage (database) consuming
too much space without much purpose. Usually there is no need to store all auth attempts for the single user
starting from his registration. Thus a built-in garbage collection mechanism provided., (*25)
Using [[\yii2tech\authlog\AuthLogIdentityBehavior]] triggers garbage collection automatically on log writing.
You may setup gcProbability
and gcLimit
to control the process or invoke gcAuthLogs()
directly., (*26)