Laravel için özel UserProvider Oluşturmak

Uygulamanızda kullanıcıların 3. parti sistemlerden sağlamanız gerektiği durumda Laravel özelinde UserProvider oluşturmanız gerekmektedir. Her ne kadar resmi dökümantasyonda konu üzerine bilgi bulunsa da sonrasında uğraşmam gerektiği konular oldu.

Herhangi bir işlem gerçekleştirmeden önce kullanıcıları tanımlamak için bir sınıf oluşturulması gerekmektedir. Bu yeni sınıf ya Illuminate\Auth\GenericUser genişletmeli ya da Illuminate\Contracts\Auth\Authenticatable uygulamasını gerçekleştirmelidir.

Temel Yapılar

Bunlarla beraber özel sağlayıcımızı yazmak için bir engel bulunmuyor. Burada arayüz üzerinden sağlayıcıyı oluşturacağım.

<?php

namespace App\Providers;

use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider as UserProviderContract;

class CustomProvider implements UserProviderContract
{
  public function retrieveById($identifier) {}

  public function retrieveByCredentials(array $credentials) {}

  public function validateCredentials(Authenticatable $user, array $credentials) {}

  public function retrieveByToken($identifier, $token) {}

  public function updateRememberToken(Authenticatable $user, $token) {}
}
CustomProvider.php

Arayüz dahilinde 5 tane uygulamasını yapmamız gereken metod bulunuyor.

retrieveById

Yapılan her çağrıda eğer oturum kurabiyesinde kullanıcı id'si bulunuyorsa çağrılıyor. Burada normal durumda kullanıcı bu id ile veri tabanından çekilerek sağlanabilir fakat bizim üçüncü parti arayüzlerden sadece id ile kullanıcı bilgisi çekmemiz güvenlik açısından sıkıntı yaratacaktır. Aynı şekilde kullanıcı bilgisine ihtiyaç duyulmasa da üçüncü partiye çağru atılması her çağrının yavaşlamasına yol açacaktır.

Bunun yerine kullanıcı bilgisini oturumda saklayabiliriz. Fakat ona nasıl erişeceğiz. retrieveById metodunda sadece id'si olan bir kullanıcı oluşturursak framework bizim için oturum bilgilerini yükleyebilir biz de oradan gerçek bilgileri çekip kullanıcıyı güncelleyebiliriz.

<?php
...
public function retrieveById($identifier)
{
  return new User(['id' => $identifier]);
}

retrieveByCredentials(array $credentials)

Bu sistemin giriş öncesi ve esnası işlemlerini gerçekleştirecek. Normal provider'da burada gelen credentials içinde bulunan email adresi ile kullanıcı veri tabanından çekilmesi yetmektedir. Fakat bizim sahip olduğumuz sistemde kimlik bilgileri 3. parti tarafından kontrol edilmektedir. Eğer doğrularda kullanıcı bilgileri değilse hata mesajı dönmektedir. Burada iki kez kullanıcı bilgileri doğrulatmaktansa gelen bilgilerle bir model oluşturup onu doğrulama esnasında kontrol etmek çok daha mantıklı olacaktır.

<?php
...
public function retrieveByCredentials(array $credentials)
{
  return new User(/* user information or errors. */);
}

validateCredentials(Authenticatable $user, array $credentials)

Kullanıcı parolasının girilen parola ile uyup uymadığının kontrol edildiği metodtur. Fakat biz bu noktada gelene kadar kullanıcı doğrulamasını çoktan yapmış bulunuyoruz. Onun yerine aldığımız kullanıcının gerçek olduğunu kontrol etmek yetecektir.

<?php
...
public function validateCredentials(Authenticatable $user, array $credentials) {
  try {
    return $user->is_successful;
  } catch (\Exception $e) {
    return false;
  }
}

Kalan metodlar beni hatırla bilgilerinin işlenmesi için kullanılmaktadır.

Kullanıcı oturumu

Kullanıcı bilgilerinin oturum üzerinde tuttuğumuz için çağrıların bir noktasında kullanıcı bilgisini kaydedip, çekmemiz gerekiyor.

Kullanıcı bilgisini LoginController içinde saklayıp, EnsureFrontendRequestHasUser middleware'i üzerinden yükleyeceğiz.

<?php
...
protected function authenticated(Request $request, $user)
{
    session(['user' => $user]);
}
...
LoginController.php
<?php
...
public function handle(Request $request, Closure $next)
{
    $user = session('user');
    if (isset($user) && isset($user->is_succesful)) {
        Auth::setUser($user);
    }
    return $next($request);
}
...
EnsureFrontendRequestHasUser.php

Son olarak özel sağlayıcımızı sisteme tanıtmamız gerekiyor.

<?php
...
public function boot()
{
  ...
  Auth::provider('custom', function($app, array $config) {
    return new CustomProvider();
  });
}
AuthUserProvider.php
<?php
...
'providers' => [
    'users' => [
        'driver' => 'custome',
        'model' => App\Models\User::class,
    ],

],
auth.php
Artık özel sağlayıcınız ile sisteme giriş yapabilirsiniz.