How to set different auth guard in laravel with auth0 - laravel

I am work on laravel with auth0 project (package is auth0/login).
My project has local auth users.
I am going to add auth method with auth0, so I have set auth config for auth0.
This is my /config/auth.php code
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'auth0web'=>[
'driver' => 'session',
'provider' => 'auth0_users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'auth0_users'=>[
'driver' => 'auth0'
],
],
this is my callback route's controller function.
public function auth0SigninCallback()
{
//return response()->json(Auth:: guard('auth0web)->user());
$service = \App::make('auth0');
// Try to get the user information
$profile = $service->getUser();
$userRepo = new Auth0UserRepository();
$auth0User = $userRepo->getUserByUserInfo($profile);
return response()->json($auth0User);
}
Auth::guard('auth0web)->user();
At this code I am getting null for auth user.
$profile is correctly getting for now.
how can I get different guard(Auth::guard('auth0web')->user()) for auth
Thanks for your advance.
PS
This is my session data maybe that is correctly
{
"_token": "OAmhhYKWeO0tK6E5FN3DHaRvVYx6PP7z0YPMAPrz",
"_previous": {
"url": "http://xxxxx.dev/login"
},
"_flash": {
"old": [],
"new": []
},
"auth0__user": {
"sub": "auth0|xxxxxxxxxxx",
"nickname": "xxxxxxxx",
"name": "xxxxx#xxxxx.com",
"picture": "https://s.gravatar.com/avatar/xxxx.png",
"updated_at": "2019-03-26T17:28:53.981Z",
"email": "xxxxxx#ixxx.com",
"email_verified": true
}
}
I have try override callback route controller
this is code
// Get a handle of the Auth0 service (we don't know if it has an alias)
$service = \App::make('auth0');
// Try to get the user information
$profile = $service->getUser();
// Get the user related to the profile
$auth0User = $this->userRepository->getUserByUserInfo($profile);
if ($auth0User) {
// If we have a user, we are going to log them in, but if
// there is an onLogin defined we need to allow the Laravel developer
// to implement the user as they want an also let them store it.
if ($service->hasOnLogin()) {
$user = $service->callOnLogin($auth0User);
} else {
// If not, the user will be fine
$user = $auth0User;
}
Auth::guard('auth0web')->login($user, $service->rememberUser());
}
// dd(auth());
// \Log::info(auth()->user());
return \Redirect::intended('/home');
}
at this time auth() is correctly working
but while redirecting to home Auth is initialized
this is my custom middleware.
public function handle($request, Closure $next)
{
// \Log::info('------------here---------');
// dd(auth());
$auth = Auth::user() ?? Auth::guard('ldap')->user();
// dd(auth());
// \Log::info(auth()->user());
if (!isset($auth->id)) {
return redirect('login');
} else {
return $next($request);
}
}
At this part I'm getting null from auth()->user()

Related

Codeigniter 4 Shield adding access/token route

I'm starting to work with Codeigniter 4 Shield.
I added this piece of code to my app/Config/Routes.php file.
$routes->get('/access/token', static function() {
$token = auth()->user()->generateAccessToken(service('request')->getVar('token_name'));
return json_encode(['token' => $token->raw_token]);
});
When I try to access the route in my web browser using the URL https://example.com/access/token, I obtain the error:
Call to a member function generateAccessToken() on null
produced by the line of code below:
$token = auth()->user()->generateAccessToken(service('request')->getVar('token_name'));
Background information:
I have installed Codeigniter 4 Shield using Composer, ran the respective database migrations, and everything else works fine.
My Codeigniter 4 Shield 'login' and 'register' pages work fine.
How can I load generateAccessToken() automatically in the app/Config/Routes.php file?
You need to submit the login credentials (email & password) along with your HTTP POST request to help identify the User requesting the access token. Otherwise, auth()->user() is empty, hence the error.
To generate an access token, you need to first authenticate the User.
For example: (Using email & password)
Define your 'access token' route. Notice the use of ->post(...) instead of ->get(...).
File: app/Config/Routes.php
$routes->post('auth/token', '\App\Controllers\Auth\LoginController::accessToken');
Define your Controller method that will handle the 'access token' generation. Read: Issuing the Tokens
File: app/Controllers/Auth/LoginController.php
<?php
namespace App\Controllers\Auth;
use App\Controllers\BaseController;
class LoginController extends BaseController
{
public function accessToken()
{
// Validate credentials
$rules = [
'email' => [
'label' => 'Auth.email',
'rules' => config('AuthSession')->emailValidationRules,
],
'password' => [
'label' => 'Auth.password',
'rules' => 'required',
],
];
if (!$this->validate($rules)) {
return $this->response
->setJSON(['errors' => $this->validator->getErrors()])
->setStatusCode(422);
}
if (auth()->loggedIn()) {
auth()->logout();
}
// Attempt to login
$result = auth()->attempt([
'email' => $this->request->getPost('email'),
'password' => $this->request->getPost('password')
]);
if (!$result->isOK()) {
return $this->response
->setJSON(['error' => $result->reason()])
->setStatusCode(401);
}
// Generate token and return to client
$token = auth()->user()->generateAccessToken($this->getDeviceName());
return $this->response
->setJSON(['token' => $token->raw_token]);
}
public function getDeviceName()
{
$agent = $this->request->getUserAgent();
if ($agent->isBrowser()) {
$currentAgent = $agent->getBrowser() . ' ' . $agent->getVersion();
} elseif ($agent->isRobot()) {
$currentAgent = $agent->getRobot();
} elseif ($agent->isMobile()) {
$currentAgent = $agent->getMobile();
} else {
$currentAgent = 'Unidentified User Agent';
}
return $agent->getPlatform() . " - " . $currentAgent;
}
}
Protect your /api routes using the $filters setting on app/Config/Filters.php. Read: Protecting Routes
Exclude your 'access token' ("auth/token") route together with all API routes ("api/*") from the global "session" & "toolbar" filters.
File: app/Config/Filters.php
<?php
// ...
class Filters extends BaseConfig
{
// ...
public array $globals = [
'before' => [
'session' => ['except' => [
"login*",
"register",
"auth/a/*",
"auth/token",
"api/*"
]],
],
'after' => [
'toolbar' => ['except' => ["auth/token", "api/*"]],
],
];
// ...
public array $filters = [
'tokens' => ['before' => ["api/*"]],
];
}
Make a one-time initial HTTP POST request to the auth/token route to receive the 'access token'. Upon receiving the token, store it with the client. I.e: in localStorage
$.ajax({
url: "https://your-site-domain.com/auth/token",
type: "POST",
data: {
"email": "USER-EMAIL-ADDRESS-HERE",
"password": "USER-PASSWORD-HERE",
},
success: function (response) {
window.localStorage.setItem('token', response.token);
},
error: function (jqXHR) {
console.log(jqXHR.responseText);
},
});
You may now send the received/stored access token using the Authorization header along with all your other protected API HTTP requests in your application without reauthenticating the user. i.e:
$.ajax({
url: "https://your-site-domain.com/api/rest/v1/employees",
type: "GET",
beforeSend: function (jqXHR) {
jqXHR.setRequestHeader(
"Authorization",
"Bearer " + window.localStorage.getItem('token')
);
},
data: {},
success: function (response) {
// Use the response here on success.
// I.e: listing all employees in a table.
},
error: function (jqXHR) {
console.log(jqXHR.responseText);
},
});

Laravel Common Api Routes for Different Authentication Guards

I have several authentication guards on my app like below:
'api' => [
'driver' => 'passport',
'provider' => 'users',
'hash' => false,
],
'api-customer' => [
'driver' => 'passport',
'provider' => 'customers',
'hash' => false,
],
'api-manufacturer' => [
'driver' => 'passport',
'provider' => 'manufacturers',
'hash' => false,
],
I have some common routes for api and api-manufacturer and I created my routes like below
Route::middleware('auth:api', 'verified')->group( function () {
Route::post('bids/job/update-quote', 'BidController#updateOrCreateQuote');
}
Route::middleware('auth:api-manufacturer')->group(function () {
Route::post('bids/job/update-quote', 'BidController#updateOrCreateQuote');
}
in this case only second route definition is working, I mean for api-manufacturer guard. I tried to add both middleware like middleware(['auth:api, auth:api-manufacturer']).... but it didn't work also. I think this checks for both auth guards..
How to do that in proper way.. I will need same approach while creating admin user..
The auth (Authenticate) middleware takes a list of possible guards to check. You can pass multiple guards to it and it will spin through them until one of them returns a user.
middleware('auth:api,api-manufacturer')
If a guard returns a user then it will also set that as the default guard.
Your solution is checking one of two guards not both, like if one of the guards passed then it pass to the route.
you have two options:
First: simplest, create a new route that redirects to the same controller method like:
Route::middleware('auth:api', 'verified')->group( function () {
Route::post('bids/job/update-quote', 'BidController#updateOrCreateQuote');
}
Route::middleware('auth:api-manufacturer')->group(function () {
Route::post('bids/job/manufacturer/update-quote', 'BidController#updateOrCreateQuote');
}
Second: add a new middle ware that check if one of the two guard passed, then it pass to route, and implemented to the route:
public function handle($request, Closure $next, $guard = null)
{
if (!Auth::guard('api')->check() && !Auth::guard('api-manufacturer')->check()) {
return redirect('/login'); // or any un auth response
}
return $next($request);
}

Why time of session with jwt-auth is 1 hour from time of login?

In laravel 7 backend rest api app I use jwt-auth and I have a problem that on login
I can work in frontend part but in 1 hour I got TOKEN_EXPIRED error.
1) I tried to set time of session bigger, but failed. On development stage I need time of session more 1 hour.
Moving on live I will set time of session 30 minutes.
2) I expected that session bigger is 1 hour from last request of logged user to backend, but not from login
I have refresh method implemented below, but looks like refresh does not work...
app/Http/Controllers/API/AuthController.php :
<?php
namespace App\Http\Controllers\API;
use App\library\CheckValueType;
use App\Settings;
use Auth;
use Config;
use DB;
use Validator;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Support\Str;
use App\UserGroup;
use App\Http\Resources\UserCollection;
use Avatar;
use Storage;
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('jwt.auth', ['except' => ['login', 'register', 'activate']]);
}
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if ($token = $this->guard('api')->attempt($credentials)) {
$loggedUser = $this->guard('api')->user();
if ($loggedUser->status != 'A') {
return response()->json(['error' => 'Unauthorized'], HTTP_RESPONSE_NOT_UNAUTHORIZED);
}
$loggedUser->last_logged = Carbon::now(config('app.timezone'));
$loggedUser->save();
$userGroupsCount = UserGroup
::getByUserId($loggedUser->id)
->count();
if ($userGroupsCount == 0) {
return response()->json(['error' => 'Unauthorized'], HTTP_RESPONSE_NOT_UNAUTHORIZED);
}
return $this->respondWithToken($token);
}
return response()->json(['error' => 'Unauthorized'], HTTP_RESPONSE_NOT_UNAUTHORIZED);
}
public function me()
{
return response()->json($this->guard('api')->user());
}
public function logout()
{
$this->guard('api')->logout();
return response()->json(['message' => 'Successfully logged out']);
}
public function refresh()
{
return $this->respondWithToken($this->guard()->refresh());
}
protected function respondWithToken($token)
{
$loggedUser = $this->guard()->user();
$user_avatar_path = 'public/' . User::getUserAvatarPath($loggedUser->id, $loggedUser->avatar);
$filenameData = User::setUserAvatarProps($loggedUser->id, $loggedUser->avatar, true);
$usersGroups = User::getUserGroupByUserId($loggedUser->id, false);
return response()->json([
'access_token' => $token,
'user' => $loggedUser,
'token_type' => 'bearer',
'user_avatar_path' => $user_avatar_path,
'filenameData' => $filenameData,
'usersGroups' => $usersGroups,
'expires_in' => $this->guard('api')->factory()->getTTL() * 999360 // I SET VERY BIG VALUE
]);
}
public function guard()
{
return \Auth::Guard('api');
}
In /config/auth.php :
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 99360, // I SET BIG VALUE
'throttle' => 98860,
],
],
'password_timeout' => 10800, // I SET BIG VALUE
In app/Exceptions/Handler.php I have:
public function render($request, Throwable $exception)
{
if ($exception instanceof UnauthorizedHttpException) {
if ($exception->getPrevious() instanceof TokenExpiredException) {
\Log::info( '-2 UnauthorizedHttpException TokenExpiredException::' ); // I SEE THIS ERROR LOGGED
return response()->json(['error' => 'TOKEN_EXPIRED'], $exception->getStatusCode());
I have :
"laravel/framework": "^7.0",
"tymon/jwt-auth": "^1.0.0",
What is wrong in my config?
MODIFIED :
I added file
app/Http/Middleware/JwtMiddleware.php with content and 1 line of error logging :
<?php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
class JwtMiddleware extends BaseMiddleware
{
public function handle($request, Closure $next)
{
try {
if (! $user = $this->auth->parseToken()->authenticate()) {
return response()->json(['success' => false, 'error' => __('Invalid User.')]);
}
} catch (TokenExpiredException $e) {
try {
$refreshed = $this->auth->refresh($this->auth->getToken());
$user = $this->auth->setToken($refreshed)->toUser();
header('Authorization: Bearer ' . $refreshed);
} catch (JWTException $e) {
return response()->json(['success' => false, 'error' => __('Could not generate refresh token')]);
}
} catch (JWTException $e) {
\Log::info( '-1 JwtMiddleware$e->getMessage() ::' . print_r( $e->getMessage(), true ) );
return response()->json(['success' => false, 'error' => __('Invalid request')]);
}
return $next($request);
}
}
and I added in file app/Http/Kernel.php :
...
protected $middleware = [
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\App\Http\Middleware\JwtMiddleware::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class
];
...
and running the page site is broken and I see lines in log :
[2020-05-27 17:08:33] local.INFO: -1 JwtMiddleware$e->getMessage() ::The token could not be parsed from the request
[2020-05-27 17:08:33] local.INFO: -1 JwtMiddleware$e->getMessage() ::The token could not be parsed from the request
[2020-05-27 17:08:33] local.INFO: -1 JwtMiddleware$e->getMessage() ::The token could not be parsed from the request
Can it be some conflict with code of app/Http/Controllers/API/AuthController.php ?
How can it be fixed ?
MODIFIED #2:
Thanks ! I fixed the error and in .env I added lines :
JWT_TTL=20 # 20 minutes
JWT_REFRESH_TTL=20160 # 2 weeks
and clearing cache I logged again and as result while working in the app I did
not logout any 20 minutes, but when I left the app opened without working with it
for period about 30 minutes I could continue working without log ou, as I expected.
Are these other options ?
MODIFIED #3:
In client part of my vuejs file I fave a request interceptors in src/App.vue:
created() {
let self = this
this.$http.interceptors.response.use(undefined, function (error) {
return new Promise(function (/*resolve, reject*/) {
if (typeof error.response.status !== 'undefined' && error.response.status === 401) {
self.$store.dispatch('logout') // DEBUGGING
self.showPopupMessage('Access', 'Not authorized !', 'warn')
let splitted0 = self.getSplitted(error.response.config.url, '/login', 0)
if (splitted0 == '') { // not move from login page
self.$router.push('/login') // DEBUGGING
}
}
if (typeof error.response.status !== 'undefined') {
if (error.response.status === 401) {
self.$store.dispatch('logout') // DEBUGGING
self.showPopupMessage('Access', 'Not authorized !', 'warn')
self.$router.push('/login') // DEBUGGING
}
}
throw error
})
})
}, // created() {
I catch 401 error in it and wonder is it possible to catch the request from the server
header('Authorization: Bearer ' . $refreshed);
and to write to new access_token value from $refreshed?
But how can I catch it? But some special return request code?
Thanks!
go to ---> config/jwt.php
You can do this
'ttl' => env('JWT_TTL', 1440)
OR in Controller
$token = JWTAuth::attempt($credentials, ['exp' => Carbon\Carbon::now()->addDays(7)->timestamp]);
OR
config()->set('jwt.ttl', 60*60*7);
OR
Config::set('jwt.ttl', 60*60*7);
You should have a config/jwt.php file. If you do not have this yet, run:
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
Within that file, you can see several properties that refer to .env variables, being:
'ttl' (env = 'JWT_TTL')
'refresh_ttl' (env = 'JWT_REFRESH_TTL')
Also, you might want to add 'refresh' to that jwt.auth middleware exception list because else it will not work when you call the refresh() function in the controller.
HOWEVER, there are some important things to note here in this package:
Authentication TTLs are linked together
I believe that you can pretty much disregard the ttl property, since its the refresh_ttl that actually defines how long your JWTs are valid, based on this analogy:
The locksmith (auth provider) gives you a Red Key (the JWT). That key allows you to open the Red Door (use your backend). The key snaps in half automatically after 5 minutes (TTL = 5min). However you can go back to the locksmith with your broken key and he will replace it for the duration of 2 weeks (Refresh TTL = 2w).
You can basically call the auth/refresh endpoint with your expired JWT and it will refresh it until the Refresh-TTL has expired.
See also [this issue on github][1] which also explains why you need to add the refresh function to not have jwt.auth middleware in front of it.
You do not save any DB calls when using the JWT as provided by this package
My initial thought was that it could save me a roundtrip to the database because the user object would be signed and ready inside the JWT.
I've used this package in several projects now and I came to the conclusion that it is somewhat of a glorified session cookie. In tymon/jwt, the sub claim simply equals 1 (or whichever user ID is referenced here).
This means you need to either...
... (default) let tymon/jwt do the work which simply retrieves the user from the database and applies it to your auth provider so Auth::user() etc will work.
OR
... add a claim yourself with a full user object and modify this package in various places. This could save you DB calls since this object will be part of and signed within your JWT. It causes more JWT bytes to send though on each request, but you can basically take the given object for granted (i.e. accept it as it is received) and use it. You can then also add permissions/roles this way so those do not need to get retrieved from the database as well. This setup DOES mean that when changing any permissions in your database, you'd have to wait for a new JWT being refreshed in order to see those changes.
try this in your login
if ($token = $this->guard('api')->attempt($credentials,['exp' => Carbon\Carbon::now()->addHours(2)->timestamp])) {
}
Or You Can chnage the ttl in config/jwt
Let Me know if it Helps!
You need to add middleware and check if token expired.
If expired check what is the generation time to check if you should generate a new token or not. Think of this as a refresh token expire time. you can skip this step if you want to generate a refresh token without any time validations.
Now if all ok generate a new token and send it in the header/ body as you wish and store that in your frontend application.
<?php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
class JwtMiddleware extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
try {
if (! $user = $this->auth->parseToken()->authenticate()) {
return response()->json(['success' => false, 'error' => __('Invalid User.')]);
}
} catch (TokenExpiredException $e) {
try {
$refreshed = $this->auth->refresh($this->auth->getToken());
$user = $this->auth->setToken($refreshed)->toUser();
header('Authorization: Bearer ' . $refreshed);
} catch (JWTException $e) {
return response()->json(['success' => false, 'error' => __('Could not generate refresh token')]);
}
} catch (JWTException $e) {
return response()->json(['success' => false, 'error' => __('Invalid request')]);
}
return $next($request);
}
}
UPDATES:
This is the method i followed in my recent Ionic/ Angular APP. And it works fine. There are ways that i have done before, but it is hard to explain, let me know when you have any problem following.
You generate a token and a refresh_token both when you successfully login and send both the tokens to your front end APP and save it there in local storage.
For all the protected APIs you now have to send the token and the refresh_token.
In the API side validate the token and if expired check if refresh_token is valid or expired. If expired you are logged out.
If refresh_token is valid generate a new token and refresh_token and send it to the front end and store it there.
There is one problem with this method, the login session should be active as long as the user is using the APP. So let's say your JWT_REFRESH_TTL is 1 day and the user is using just before 24Hrs, it will work before 24Hr are passed but it will not work just after 1 min as both token and refresh_token both will expire.
To overcome this you can generate a new refresh_token with each API request and update it in your frontend.
Generally, the JWT_TTL should be very short like 5 mins or so and JWT_REFRESH_TTL should be the session active time.
As other people suggested to you, go to your config/jwt.php and modify the token expiration limit:
// ...
'ttl' => env('JWT_TTL', 3600)
Important: After changing that, clear your config cache
php artisan config:clear
Also, note that previous generated tokens will have their own claims so it's likely that those tokens won't follow the modified rule.
Side note
As an alternative to implementing the JWT yourself, you could make use of Sanctum, a new first-party Laravel package. Check the SPA mode in the Sanctum documentation.

Laravel 7 authentication not persisting

I have a custom guard and provider defined in config/auth.php:
'guards' => [
// ...
'interviewers' => [
'driver' => 'session',
'provider' => 'interviewers',
],
// ...
],
'providers' => [
// ...
'interviewers' => [
'driver' => 'eloquent',
'model' => App\Interviewer::class,
],
// ...
],
My App\Interviewer model extends Illuminate\Foundation\Auth\User.
My authentication route authenticates correctly:
public function login($token)
{
$interviewer = Interviewer::where('token', $token)
->firstOrFail();
auth('interviewers')->login($interviewer);
$interviewer->update(['logged_in_at' => now()]);
// outputs: "in login controller - 1"
dump('in login controller - ' . auth('interviewers')->check());
return redirect()->route('interviews.edit');
}
However in my route with an auth middleware,
Route::middleware('auth:interviewers')->group(function () {
Route::get('/interview/{form?}', 'InterviewController#edit')
->name('interviews.edit');
});
it's never authenticated and redirects me to the login route. Doing some debugging in Illuminate\Auth\Middleware\Authenticate:
protected function authenticate($request, array $guards)
{
if (empty($guards)) {
$guards = [null];
}
foreach ($guards as $guard) {
// outputs "interviewers middleware - "
dump($guard . ' middleware - ' . $this->auth->guard($guard)->check());
if ($this->auth->guard($guard)->check()) {
return $this->auth->shouldUse($guard);
}
}
$this->unauthenticated($request, $guards);
}
When doing artisan route:list, here are my routes:
GET|HEAD | interviews/{token} | interviewers.login | App\Http\Controllers\Auth\InterviewerLoginController#login | web
GET|HEAD | interview/{form?} | interviews.edit | App\Http\Controllers\InterviewController#edit | web,auth:interviewers
I've read that because routes don't have the web middleware the authentication won't persist, but as you can see web is included by default. I have another custom guard that uses "traditional" username + password. It's working as expected.
My env for session is SESSION_DRIVER=file, my other guards are working as expected.
UPDATE
I forgot to mention that I have a test for this and it passes:
public function test_can_log_in_with_valid_token()
{
$applicant = Applicant::all()->random();
$interviewer = factory(Interviewer::class)->make();
$interviewer->token = Str::random();
$interviewer = $applicant->interviewers()->save($interviewer);
$this->get(route('interviewers.login', $interviewer->token))
->assertRedirect();
$this->assertAuthenticatedAs($interviewer, 'interviewers');
}
Typical ID10T error on my part. I didn't realize that I had implemented Illuminate\Contracts\Auth\Authenticatable manually on my model before extending the Illuminate\Foundation\Auth\User class. PHPStorm had stubbed out those methods for me...
Removing those stubbed methods worked.
Hello in you login method use attempts function that is a function that login user I think with persistence. Auth::attempts([‘email’ => $request->email, ´password’ => $request->password]);
That will verify if user can be connected or rejected ( it’s the default Authenticator).

Strange error on JWT Laravel when using Multi Tenant Application

I'm using this package for "jwt-auth" for my Laravel backend project, here is the link for the package:
https://jwt-auth.readthedocs.io/en/develop/
I have 2 middleware that I put the names Tenant and JWT, when my user tries to log in to the app he must send the company code, so my middleware Tenant picks the information from the specific connection database client and all is working fine.
But when I use 2 middlewares together, he gives me an error that I don't have a user table. He is right because when I made a searching from the problem I found that the package executes a function before all my 2 middlewares that is this:
/**
* Get the currently authenticated user.
*
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function user()
{
// MODIFICAÇÃO CUSTOMIZADA DA FUNÇÃO USER
if ($this->user !== null) {
return $this->user;
}
if ($this->jwt->setRequest($this->request)->getToken() &&
($payload = $this->jwt->check(true)) &&
$this->validateSubject()
) {
return $this->user = $this->provider->retrieveById($payload['sub']);
}
}
The problem was solved if I comment this line "return $this->user = $this->provider->retrieveById($payload['sub']);", but this is not a good practice. The main reason for this error is that this function is executed before my Tenant middleware that doesn't have a user table in the database that Tenant middleware tries to connect.
The file name is **JWT_GUARD.php in tymon\jwt-auth\src**, i'm think is something about my configuration that i must change in
config/auth.php from laravel
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
And here:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
I comment on this part "return $this->user = $this->provider->retrieveById($payload['sub']);" and waiting for a better solution

Resources