It looks ugly and overcomplicated, but I guess it should work. Why did you go with static methods? Changing to something else will be difficult. Testing not so easy. Not sure if that is final version and if you are showing everything but from what I see you are breaking quite a few programming principles.
Database-less user authentication: Is my solution okay?
Hello everybody,
I needed to authenticate my users not using the database of my Laravel-app but using the database of another Laravel-app, which provides OAUTH2 using passport.
The important thing: The OAUTH2-server is not accessible for the users - it's only accessible for the public Laravel app using a private network.
So unfortunately I cannot use Socialite or something like this for my public Laravel app.
So this is my solution based on https://gist.github.com/eusonlito/8b5389db1d390c17aba123645fd99ea1 and I would like to hear your comments on this implementation and possible security risks:
app/Http/Controllers/Auth/LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Services\User\Auth;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class LoginController extends Controller
{
use AuthenticatesUsers;
[...]
public function login(Request $request)
{
$user = Auth::byCredentials($request->input('email'),
$request->input('password'));
return $user;
}
}
app/Providers/AuthServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth as BaseAuth;
use App\Services\Auth\UserProvider;
class AuthServiceProvider extends ServiceProvider
{
protected $policies
= [// 'App\Model' => 'App\Policies\ModelPolicy',
];
public function boot()
{
$this->registerPolicies();
$this->provider();
}
protected function provider(): void
{
BaseAuth::provider('custom', static function ():
UserProvider {
return new UserProvider();
});
}
}
app/Repositories/User.php
<?php
namespace App\Repositories;
use App\Http\Services\ApiClient;
class User extends RepositoryInterface
{
public static function detail(): \App\User
{
$client = new ApiClient();
$client->setMethod('GET');
$client->setRoute('/api/user');
$client->setToken(session('token'));
$response = $client->execute();
$user = json_decode($response, true)['data'];
$user['token'] = $client->getToken();
return new \App\User($user);
}
}
app/Services/Auth/UserProvider.php
<?php
namespace App\Services\Auth;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider as AuthProvider;
use App\Repositories;
class UserProvider implements AuthProvider
{
public function retrieveById($identifier): Authenticatable
{
return Repositories\User::detail();
}
public function retrieveByToken($identifier, $token)
{
}
public function updateRememberToken(Authenticatable $user, $token)
{
}
public function retrieveByCredentials(array $credentials)
{
}
public function validateCredentials(Authenticatable $user, array $credentials)
{
}
}
app/Services/User/Auth.php
<?php
namespace App\Services\User;
use App\Http\Services\ApiClient;
use App\User;
use Illuminate\Support\Facades\Auth as BaseAuth;
class Auth
{
public static function byCredentials(
string $user,
string $password
) {
$client = new ApiClient();
$client->setMethod('GET');
$client->setRoute('/api/user');
$client->setCredentials([
'username' => $user,
'password' => $password,
]);
try {
$response = $client->execute();
} catch (\Exception $e) {
$validation = response()->json([
'message' => json_decode($e->getMessage())->message,
], $e->getCode());
$loginresponse = $client->validateResponse($validation);
if ($loginresponse !== true) {
return $loginresponse;
}
}
$user = json_decode($response, true)['data'];
$user['token'] = $client->getToken();
return static::auth(new User($user));
}
protected static function auth(User $user): User
{
static::session($user);
static::bind($user);
static::login($user);
return $user;
}
protected static function session(User $user): void
{
session(['token' => $user->token]);
}
protected static function bind(User $user): void
{
app()->bind('user', static function () use ($user): User {
return $user;
});
app()->bind('token', static function (): string {
return session('token');
});
}
protected static function login(User $user): void
{
BaseAuth::login($user, true);
}
}
app/User.php
<?php
namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
class User extends Models\ModelInterface implements AuthenticatableContract
{
use Authenticatable;
public function getAuthIdentifierName(): string
{
return 'token';
}
public function getAuthIdentifier(): string
{
return $this->token;
}
}
Please or to participate in this conversation.