I'm using Laravel Sanctum 3.x in my Laravel 9 project. I'm building a Microservice feature and need to authenticate them via my Microservice model where I've added HasApiTokens and created my tokens.
I've created the extra auth config:
'guards' => [
'api' => [
'driver' => 'session',
'provider' => 'users',
],
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'microservice' => [
'driver' => 'session',
'provider' => 'microservices',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'microservices' => [
'driver' => 'eloquent',
'model' => App\Models\Microservice::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
Then, inside my controller where I'd like to use my microservice auth check rather than the default auth:sanctum middleware check I'm confused as to what to add?
This is my controller:
<?php
namespace App\Http\Controllers\Hub;
use App\Http\Controllers\Controller;
use App\Http\Responses\ApiSuccessResponse;
use App\Http\Responses\ApiErrorResponse;
use App\Http\Responses\ApiValidationErrorResponse;
use Illuminate\Http\Request;
use App\Models\Microservice;
class HubController extends Controller
{
/**
* Instantiate a new HubController instance.
*
* #return void
*/
public function __construct()
{
// TODO: how to change to Microservice auth?
$this->middleware('auth:sanctum');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function __invoke(Request $request)
{
return new ApiSuccessResponse(null, [
'message' => 'Hub controller - post'
]);
}
}
Would I just need to change the auth:sanctum to auth:microservice and then it would validate the token?
You need to pass guard to your authentication logic .
if(auth()->guard('microservices')->attempt($request->only('email','password'))) {
return auth()->guard('admin')->user(); }
Related
I am trying to authenticate admin in Laravel project. my auth.php as shown below:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
AdminController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdminController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function adminLogin(){
return view('auth.adminLogin');
}
public function cheackAdminLogin(Request $request){
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:6'
]);
if (Auth::guard('admin')->attempt(['email' => $request->email,
'password' => $request->password])) {
return redirect()->intended('/admin');
}
return back()->withInput($request->only('email')); */
}
}
AdminDashboardController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AdminDasboardController extends Controller
{
public function adminPanel()
{
return view('adminPanel');
}
}
The problem that I encountered that when I want to check the admin login, the attempt() function when I wrote it, I get an error message in the editor "Undefined Method".
I tried to using auth()->guard('admin')->attempt() instead of Auth::guard('admin')->attempt but the problem is same.
please help
It may be a problem of type hint
use Illuminate\Auth\SessionGuard;
/** #var SessionGuard $adminGuard */
$adminGuard = Auth::guard("admin");
if ($adminGuard->attempt($credentials)) {
...
In laravel 5.7 there is "Authenticate.php" file that looks like this:
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
}
I have set admin guard for the admin user type (auth.php):
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'admin-api' => [
'driver' => 'token',
'provider' => 'admins',
],
],
How can i get the guard type from $request, so that I can check if the $guard name is "admin" set a different redirect page. Most tutorials are not covering 5.7 version yet.
Thanks a lot in advance
I think I had your issue, you can follow this question and answer, I hope to help you.
How to check multiple gaurd in same laravel controller OR route
https://stackoverflow.com/a/49871781/9246297
I have 4 types of users in my application and details are stored in 4 different tables, so how can I implement Laravel's Authentication?
Route::post('/adlogin', 'mainController#adminlogin');
Route::get('/sellerlogin', function () {
return view('seller.pages.login');
});
Route::post('/sellerlog_in', 'mainController#sellerlogin');
Use this as your controller
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
//Use Dependencies
use Auth;
class AdminLoginController extends Controller
{
Middleware used here is admin which you have to create in config/auth.php
public function __construct()
{
$this->middleware('guest:admin', ['except'=>'logout']);
}
Create a view for your admin Login
public function showLoginForm()
{
return view('auth.admin_login');
}
public function login(Request $request)
{
//Validate the Form Data
$this->validate($request, [
'email'=>'required|email',
'password'=>'required|min:5'
]);
//Attempt to log the Admin In
$email= $request->email;
$password= $request->password;
$remember= $request->remember;
After Successfully login where you want to redirect like here I am redirecting
toadmin.dashboard
//If Successful redirect to intended location
if (Auth::guard('admin')->attempt(['email' => $email, 'password' => $password], $remember)) {
return redirect()->intended(route('admin.dashboard'));
}
//If Unsuccessful redirect back to login form with form data
return redirect()->back()->withInput($request->only('email', 'remember'));
}
/**
* Log the Admin out of the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function logout()
{
Auth::guard('admin')->logout();
return redirect()->route('admin.login');
}
}
After logout redirect back to login page
Make sure you are using right guard for right User. Create same functionality for more user types as you want create guards for them.
In config/app.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'admin-api' => [
'driver' => 'token',
'provider' => 'admins',
],
],
As admin and admin-api created here create for your user types
Add providers
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
],
At last for resetting passwords use this.
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
'admins' => [
'provider' => 'admins',
'table' => 'password_resets',
'expire' => 10,
],
],
In http/middleware/redirectIfAuthenticated.php add this to your handle function
//Check for admin login guard
switch ($guard) {
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect()->route('admin.dashboard');
}
break;
default:
if (Auth::guard($guard)->check()) {
return redirect('/dashboard');
}
break;
}
You can add more cases for your user types.
This is all you want to create multi auth. As you created different table for different roles you have to follow this process.
Create LoginController for all user types or use your logic to log them in.
Add your guards for every user type in auth.php
Add your cases to RedirectIfAuthenticated
You can use the laravel-permission package.This package allows you to manage user permissions and roles in a database.
I am learning laravel and i decided to make a custom authentication in laravel . I could register my users but when i try to login i get this error ?
Type error: Argument 2 passed to Illuminate\Auth\SessionGuard::__construct() must implement interface Illuminate\Contracts\Auth\UserProvider, null given,
These are my resources
My AdminUser Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Notifications\Notifiable;
use Illuminate\Auth\Authenticatable as AuthenticableTrait;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
class AdminUser extends Eloquent implements AuthenticatableContract,AuthorizableContract
{
public $table = "admin_users";
use Notifiable;
use AuthenticableTrait;
use Authorizable;
protected $fillable = [
'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
My AdminUserController
<?php
namespace App\Http\Controllers;
use App\AdminUser;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\RegisterRequest;
use Auth;
use Response;
class AdminUserController extends Controller {
use AuthenticatesUsers;
/**
* the model instance
* #var AdminUser
*/
protected $user;
/**
* The Guard implementation.
*
* #var Authenticator
*/
protected $admin;
/**
* Create a new authentication controller instance.
*
* #param Authenticator $admin
* #return void
*/
public function __construct(Guard $admin, AdminUser $user)
{
$user = AdminUser::first();
Auth::login($user);
$this->middleware('admin', ['except' => ['getLogout']]);
}
/**
* Show the application registration form.
*
* #return Response
*/
public function getRegister()
{
return view('admin/admin_users/register');
}
/**
* Handle a registration request for the application.
*
* #param RegisterRequest $request
* #return Response
*/
public function postRegister(RegisterRequest $request)
{
AdminUser::create([
'email' => $request->email,
'password' => bcrypt($request->password),
]);
return redirect('backend-admin/dashboard');
}
/**
* Show the application login form.
*
* #return Response
*/
public function getLogin()
{
return view('admin/admin_users/login');
}
/**
* Handle a login request to the application.
*
* #param LoginRequest $request
* #return Response
*/
public function postLogin(LoginRequest $request)
{
if (Auth::guard('admin')->attempt($request->only('email', 'password')))
{
return redirect()->intended('/backend-admin/dashboard');
}
return redirect('/backend-admin')->withErrors([
'email' => 'The credentials you entered did not match our records. Try again?',
]);
}
/**
* Log the user out of the application.
*
* #return Response
*/
public function getLogout()
{
Auth::guard('admin')->logout();
return redirect('/backend-admin');
}
protected function guard()
{
return Auth::guard();
}
}
My VerifyAdmin Middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Support\Facades\Auth;
class VerifyAdmin
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $admin;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
// dd($auth);
$this->admin = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->admin->guest())
{
if ($request->ajax())
{
return response('Unauthorized.', 401);
}
else
{
return redirect()->guest('backend-admin');
}
}
return $next($request);
}
}
I also defined guards in auth.php
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admin' => [
'driver' => 'eloquent',
'model' => App\AdminUser::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
],
];
Also defined middleware in kernel.php
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'admin' => \App\Http\Middleware\VerifyAdmin::class,
Feel free to correct me if i am wrong anywhere or if i have missed anything .
I found what was bugging my program , i did defined guard function in my controller but forget to add the guard in function , i fixed it by defining guard.
I think the problem are those 2 lines:
$user = AdminUser::first();
Auth::login($user);
What's the point of running it? First of all, I see you have here login action and it seems you automatically login admin when on login page - it doesn't make much sense.
Also those 2 lines won't do anything that should be done I think - because when admin logs in, well you log him in so there's no point to login him in each request assuming you are using sessions.
You need to change the admin provider name from admin to admins.
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [ // ***this is the change that should be made***
'driver' => 'eloquent',
'model' => App\AdminUser::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
],
];
I'm trying to set up two authentication guards: internal (for normal browser requests) and api for AJAX requests. api is the default guard, but I'm focusing on getting the internal-guard to work, for now.
This is my config/auth.php:
<?php
return [
'defaults' => [
'guard' => 'api',
'passwords' => 'clients',
],
'guards' => [
'internal' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'clients',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'clients' => [
'driver' => 'eloquent',
'model' => App\Client::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
],
];
This is my routes.php:
<?php
Route::group([
'domain' => 'internal.example.com',
'middleware' => ['web', 'auth:internal']
], function () {
Route::get('/', function () {
return view('welcome');
});
Route::get('/home', 'HomeController#index');
});
Route::group([
'domain' => 'internal.example.com',
'middleware' => [ 'web']
], function () {
Route::match(['get', 'post'], '/login', 'InternalAuth\InternalAuthController#login');
Route::get('/logout', 'InternalAuth\InternalAuthController#logout');
});
This is InternalAuthController:
<?php
namespace App\Http\Controllers\InternalAuth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class InternalAuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/';
protected $guard = 'internal';
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
}
Seems fine to me. But when I go to /, /home or /login in my browser, I end up in a redirect loop.
I'm missing something... Any ideas?
/login points to InternalAuth\InternalAuthController#login. login() is a method of Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers (used by InternalAuth), but it is not responsible for returning the view or responding to post requests. This is a job for getLogin and postLogin.
So, I needed to change this in the routes.php:
Route::match(['get', 'post'], '/login', 'InternalAuth\InternalAuthController#login');
To this:
Route::get('/login', 'InternalAuth\InternalAuthController#getLogin');
Route::post('/login', 'InternalAuth\InternalAuthController#postLogin');