Skip to content

Authentication Documentation.

Amirul Islam Anirban edited this page Oct 28, 2023 · 11 revisions

Table of Contents

Manually Authenticating Users:

Micro framework's authentication facilities are made up of "guards". Guards define how users are authenticated for each request. For example, framework ships with a session guard which maintains state using session storage.

Config:

Your application's authentication configuration file is located at config/auth.php:

return [
    /**
     * Set Default authentication guards.
     */
    'defaults' => 'web',

    /**
     * Define multiple guards.
     */
    'guards'   => [
        'web'    => [
            'provider' => 'users',
            'model' => App\Models\Users::class,
        ],

         // Custom guard.
        'editor' => [
            'provider' => 'editors',
            'model' => App\Models\Editors::class,
        ],
    ],
];

Retrieving The Authenticated User:

You will often need to interact with the currently authenticated user. While handling an incoming request, you may access the authenticated user via the Auth facade's user method:

Auth::user();

or

auth()->user();

If needed, you may specify an authentication guard before calling the login method:

auth()->guard('editor')->user();

Determining If The Current User Is Authenticated:

To determine if the user making the incoming HTTP request is authenticated, you may use the check method on the Auth facade. This method will return true if the user is authenticated:

if (Auth::check()) {
    // The user is logged in...
}

Manually Authenticating:

The framework gives you a method called "attempt". With the help of which you can login very easily. The attempt method is normally used to handle authentication attempts from your application's "login" form.

(new AuthAttempt())->attempt(['email' => $email, 'password' => $password]);

The login Request Form:

First, we will define the routes that are needed to request login. To get started, we will define a route that returns a view with the 'login' form:

Router::get('/login', [AuthenticatedController::class, 'create'])->name('login')->middleware('guest');

Handling The Form Submission:

Of course, we need to define a route to actually submit the login form. This route will be responsible for validating incoming requests and logging in the user:

Router::post('/login', [AuthenticatedController::class, 'store'])->name('login')->middleware('guest');
/**
 * Handle an authentication attempt.
 */
public function store(Request $request) {
    $validator = new Validator();

    $validation = $validator->validate($request->only('email', 'password'), [
        'email'    => 'required|email',
        'password' => 'required|min:6',
    ]);

    if ($validation->fails()) {
        $errors = $validation->errors();

        return back()->withError($errors);
    } else {
        $validatedData = $validation->getValidatedData();

        (new AuthAttempt())->attempt($validatedData);
    }
}

The attempt method accepts an array of key / value pairs as its first argument. The values in the array will be used to find the user in your database table. So, in the example above, the user will be retrieved by the value of the email column. If the user is found, the hashed password stored in the database will be compared with the password value passed to the method via the array. You should not hash the incoming request's password value, since the framework will automatically hash the value before comparing it to the hashed password in the database. An authenticated session will be started for the user if the two hashed passwords match.

Remember, Micro framework's authentication services will retrieve users from your database based on your authentication guard's configuration. The default config/auth.php configuration file instructs the app to use the app\Models\Users model when retrieving users. You may change these values within your configuration file based on the needs of your application.

If authentication is successful it will redirect to '/' route. Otherwise, redirect back with error data. By default the route as the second argument will be the path '/'. You can change the redirect link if you want.

(new AuthAttempt())->attempt($validatedData, '/dashboard');

If needed, you may specify an authentication guard before calling the login method.

(new AuthAttempt())->guard('editor')->attempt($validatedData, '/editors/dashboard');

Get & Show validation errors:

<?= errors('email')?>

With example:

<form>
   <div class="mb-3">
       <label for="exampleInputEmail" class="form-label">Email address</label>
       <input type="email" name="email" class="form-control" id="exampleInputEmail" aria-describedby="emailHelp">

       <div id="emailHelp" class="form-text"> <?= errors('email')?> </div>
   </div>
</form>

Get & Show not found email error message:

<?= error()?>

With example:

<form>
    <?php if (hasError()): ?>
        <div class="alert alert-success mt-3" role="alert">
            <?= error() ?>
        </div>
    <?php endif?>
</form>

Logging Out:

To manually log users out of your application, you may use the destroy method provided by the Auth facade. This will remove the authentication information from the user's session so that subsequent requests are not authenticated.

Handling The Delete request:

First, we will define the routes that are needed to request logout.

Router::delete('/logout', [AuthenticatedController::class, 'destroy'])->name('logout')->middleware('auth');

If logout is successful it will redirect to '/login' route. By default the route as the second argument will be the path '/login'. You can change the redirect link if you want.

public function destroy() {
    (new AuthAttempt())->destroy();
}

If needed, you may specify an authentication guard before calling the login method.

public function destroy() {
    (new AuthAttempt())->guard('editor')->destroy('/editors/login');
}

Manually Registration Users:

The framework gives you a method called "register". With the help of which you can register very easily. The register method is normally used to handle registration from your application's "register" form.

First, we will define the routes that are needed to request register. To get started, we will define a route that returns a view with the 'register' form:

The register Request Form:

Router::get('/register', [RegisteredUserController::class, 'create'])->name('register')->middleware('guest');

Handling The Form Submission:

Of course, we need to define a route to actually submit the register form. This route will be responsible for validating incoming requests and registering in the user:

Router::post('/register', [RegisteredUserController::class, 'store'])->name('register')->middleware('guest');
public function store(Request $request) {
    $validator = new Validator();

    $validation = $validator->validate($request->only('name', 'email', 'password', 'confirm_password'), [
        'name'             => 'required',
        'email'            => 'required|email',
        'password'         => 'required|min:6',
        'confirm_password' => 'required|same:password',
    ]);

    if ($validation->fails()) {
        $errors = $validation->errors();

        return back()->withError($errors);
    } else {
        $validatedData = $validation->getValidatedData();

        unset($validatedData['confirm_password']);

        (new AuthRegister())->register($validatedData);
    }
}

The register method accepts an array of key / value pairs as its first argument. A user will be created from the data in that array.

If registration is successful it will redirect to '/login' route. Otherwise, a "DatabaseErrorException" is returned. By default the route as the second argument will be the path '/login'. You can change the redirect link if you want.

(new AuthRegister())->register($validatedData, '/custom/login');

If needed, you may specify an authentication guard before calling the login method:

(new AuthRegister())->guard('editor')->register($validatedData, '/editors/login');

If registration successful redirect /login and show success message:

Get & Show success message:

<?=success()?>

With example:

<form>
    <?php if (hasSuccess()): ?>
        <div class="alert alert-success mt-3" role="alert">
            <?=success()?>
        </div>
    <?php endif?>
</form>

Manually Forget Password Users:

Most web applications provide a way for users to reset their forgotten passwords. Rather than forcing you to re-implement this by hand for every application you create, Micro framework provides convenient services for sending password reset links and secure resetting passwords.

The sendLink method is normally used to handle send link from your application's "forget" form.

Password Reset Link Request Form:

First, we will define the routes that are needed to request password reset links. To get started, we will define a route that returns a view with the password reset link request form:

Router::get('/forgot-password', [PasswordResetLinkController::class, 'create'])
    ->name('forgot.password')->middleware('guest');

The view that is returned by this route should have a form containing an email field, which will allow the user to request a password reset link for a given email address.

Handling The Form Submission:

Next, we will define a route that handles the form submission request from the "forgot password" view. This route will be responsible for validating the email address and sending the password reset request to the corresponding user. This route will be responsible for validating incoming requests and sending links to the user's mail address:

Router::put('/forgot-password', [PasswordResetLinkController::class, 'store'])
    ->name('forgot.password')->middleware('guest');
public function store(Request $request) {
    $validator = new Validator();

    $validation = $validator->validate($request->only('email'), [
        'email' => 'required|email',
    ]);

    if ($validation->fails()) {
        $errors = $validation->errors();

        return back()->withError($errors);
    } else {
        $validatedData = $validation->getValidatedData();

        $email = $validatedData['email'];

        (new AuthReset())->sendLink($email);
    }
}

The sendLink method accepts the email value as its first argument. If the reset link is sent successfully, a mail will be sent to your mail address with the reset link. Otherwise, redirect back with an error message if the email is not found, or returns a "DatabaseErrorException" if there is a database error. By default the route as the second argument will be the path '/reset'. You can change the path if you want.

(new AuthReset())->sendLink($email);

If needed, you may specify an authentication guard before calling the login method:

(new AuthReset())->guard('editor')->sendLink($email);

Your reset link will be:- "http://localhost:8000/reset?reset=ed9cdbc206c4e440f70cea5740932400c2c1a1a3e53ce7168460fb60868d2bc6316a0e403c63a0d7&email=editor@mail.com"

If you change the reset path:

(new AuthReset())->sendLink($email, 'your-reset-path');

Then the link will be like:- "http://localhost:8000/your-reset-path?reset=ed9cdbc206c4e440f70cea5740932400c2c1a1a3e53ce7168460fb60868d2bc6316a0e403c63a0d7&email=user@mail.com"

Get & Show not found email error message:

<?= error()?>

With example:

<form>
    <?php if (hasError()): ?>
        <div class="alert alert-success mt-3" role="alert">
            <?= error() ?>
        </div>
    <?php endif?>
</form>

Resetting The Password:

The Password Reset Form:

Next, we will define the routes necessary to actually reset the password once the user clicks on the password reset link that has been emailed. This route will receive a token param that we will use later to verify the password reset request:

Router::get('/reset', [NewPasswordController::class, 'create'])->name('reset')->middleware('guest');

The view that is returned by this route should display a form containing an email field, a password field, a password_confirmation field, and a hidden token field, which should contain the value of the secret $token received by our route.

Handling The Form Submission:

Of course, we need to define a route to actually handle the password reset form submission. This route will be responsible for validating the incoming request and updating the user's password in the database:

Router::put('/reset', [NewPasswordController::class, 'store'])->name('reset')->middleware('guest');
public function store(Request $request) {
    $validator = new Validator();

    $validation = $validator->validate($request->only('reset_token', 'email', 'password', 'confirm_password'), [
        'reset_token'      => 'required',
        'email'            => 'required|email',
        'password'         => 'required|min:6',
        'confirm_password' => 'required|same:password',
    ]);

    if ($validation->fails()) {
        $errors = $validation->errors();
        return back()->withError($errors);
    } else {
        $validatedData = $validation->getValidatedData();
        (new AuthReset())->resetPassword($validatedData);
    }
}

The resetPassword method accepts an array of key/value pairs as its first argument. That array will be validated by data token and email to see if you are valid for this request, if the email and token is valid your new password will be set.

If reset password is successful it will redirect to '/login' route. Otherwise, redirect back with an error message if the email or token is not found, or returns a "DatabaseErrorException" if there is a database error. By default '/login' route will be given. You can change the redirect link if you want.

(new AuthReset())->resetPassword($validatedData, '/custom/login');

If needed, you may specify an authentication guard before calling the login method:

(new AuthReset())->guard('editor')->resetPassword($validatedData, '/editors/login');

After resetting the password, the token will be automatically deleted from the database.

Get & Show not found email error message:

<?= error()?>

With example:

<form>
    <?php if (hasError()): ?>
        <div class="alert alert-success mt-3" role="alert">
            <?= error() ?>
        </div>
    <?php endif?>
</form>