i am using passport authentication for my Laravel 5.4 API.here i have a api for company details and it is a non auth api.i need to check logined user liked this company using auth in this url ...how i can do this.
This is my route
Route::get('/company/{company}','Api\V1\CompanyController#show');
Route::group(['middleware' => 'auth:api','prefix'=>'v1'], function(){
//auth urls
}
and this is my controller
class CompanyController extends Controller
{
public function show(Company $company,Request $request)
{
$data = array();
$flag = 0;
$data['status'] = 1;
$data['message'] = 'success';
$data['baseUrl'] = url('/');
$data['is_login'] = Auth::check();
Here is_login always return false,if i added autherization token in headers of api.
What is your default guard set as?
Auth::check() is Auth::guard(null)->check() which uses the current default guard.
If you want to check for an api you probably want to use the api guard just like your auth middleware is using when you use auth:api.
Auth::guard('api')->check() tells it to explicitly use the api guard instead of what the default is, which could be anything since we don't know what you have set.
When the auth middleware is ran it actually will set the default guard for you depending upon what guards are passed to it and which one it can resolve a user from. Which is why you can just call Auth::user() and get the correct user from the correct guard, because the middleware sets the current to the one that resolved the user. (When calling routes that have this middleware)
Related
I Made Laravel Project And install the Breeze package for multi authentication And the Create a guard call admin in order to control user assess to dashboard It works fine Here is the route
Route::get('/dashbord',[AdminController::class, 'Dashbord'])
->name('admin.dashbord')
->middleware('Admin');
Route::get('/profile/edit',[AdminProfileSettings::class, 'index'])
->name('admin.profile.settings')
->middleware('Admin');
Here Is the middleware
public function handle(Request $request, Closure $next)
{
if(!Auth::guard('admin')->check()) {
return redirect()->route('login_form')->with('error','please Login First');
}
return $next($request);
}
This code works fine but the problem is when I log in to the dashboard and try to get admin ID to admin.profile.settings route it wont get the Id, I Passed the logged admin id by using AdminProfileSettings controller like this
public function index()
{
$id=Auth::user()->id;
$adminData = Admin::find($id);
return view('admin.admin_profile_settings',compact('adminData'));
}
But, when I try to access it in the admin.admin_profile_settings view it show me this error:
Trying to get property 'id' of non-object
But, if I use $adminData = Admin::find(1); it get the Id without any problem but when I try to get auth user id it show me the error and if I have logged in using default guard this error wont show but it get the id from users table
You're not using the auth:admin middleware, so the Auth facade is going to pull the user from the default guard defined in the config (which is web, unless you've changed it).
Without using the auth:admin middleware, you'll need to specify the guard for which to get the user.
$adminUser = Auth::guard('admin')->user();
Note 1: if you have the $request variable, you can also pull the user off of the $request with $request->user(), instead of reaching out to the Auth facade. It's just a matter of preference. The user() method also takes a guard as a parameter, if needed.
$adminUser = $request->user('admin');
Note 2: the user() method (Auth and request) returns the fully hydrated model. There is no need to get the id and re-retrieve the model.
How would you guys go about implementing something like this? I use Laravel as an API only. We have other framework where the login was implemented where it saves an httpOnly cookie (sessionId) after the user logs in. That's the main framework. We're migrating away from that old framework (Zend).
With the sessionId sent to Laravel from, say, a JS frontend, I'm able to lookup the current user based on the sessionId. That sessionId is then used to query the session database. I've created a middleware called "CheckForCurrentUser.php":
[..]
public function handle(Request $request, Closure $next)
{
// The reason for this is that the OPTIONS (request) does not include the cookie in the request.
$method = $request->method();
// SESSIONID is the name of the cookie created from the main framework
// once a user is logged in.
// SESSIONID is an exception in EncryptCookies.php
$sessionId = request()->cookie('SESSIONID');
if ($method === 'POST' && $sessionId !== '') {
// This function is only to get the logged in user id from the session database
$userId = $this->notImportantFunction($sessionId);
if ($userId) {
// User id found so make current user for this Laravel API
Auth::loginUsingId($userId);
} else {
// Instructs the frontend to let user log back in.
return abort(401);
}
}
return $next($request);
}
To recap, a user cannot authenticate from this Laravel application nor can I send an authentication token. They logged in from another framework. Laravel has access to the main framework databases.
This setup works. Using use Illuminate\Support\Facades\Auth; I use that as the "current user" in any controller/model.
Kernel.php looks something like:
[..]
protected $middleware = [
[..]
\App\Http\Middleware\CheckCurrentUser::class,
[..]
];
Before I go any further, is that how you'd implement something like this? It does work (ish) but I do not get the SESSIONID unless I check for a POST request.
I do not like this setup. I'm now using lighthouse and having issues using both the #auth and #inject directives. This is due to how I authenticate a use with Laravel so sorting how I authenticate a user should sort Lighthouse. Any tips on how to refactor this the right way? My routes are with /api/some-string
Lighthouse is not the issue. Should I send a authentication header, Lighthouse works. I believe Laravel does something behind the scenes with it sees a token in the header. I cannot send an authentication. I can only rely on the cookie. It's httpOnly so I have no access to that from JavaScript.
I am using Passport to log in users to a Laravel API endpoint, users get authenticated using their social accounts (google, facebook) using laravel-socialite package.
the workflow of logging users in and out works perfectly (generating tokens...Etc). The problem is I have a controller that should return data based on whether there is a user logged in or not.
I do intercept the Bearer token from the HTTP request but I couldn't get the user using the token (I would use DB facade to select the user based on the token but I am actually looking whether there is a more clean way already implemented in Passport)
I also don't want to use auth:api middleware as the controller should work and return data even if no user is logged in.
this is the api route:
Route::get("/articles/{tag?}", "ArticleController#get_tagged");
this is the logic I want the controller to have
public function get_tagged($tag = "", Request $request)
{
if ($request->header("Authorization"))
// return data related to the user
else
// return general data
}
Assuming that you set your api guard to passport, you can simply call if (Auth::guard('api')->check()) to check for an authenticated user:
public function get_tagged($tag = "", Request $request)
{
if (Auth::guard('api')->check()) {
// Here you have access to $request->user() method that
// contains the model of the currently authenticated user.
//
// Note that this method should only work if you call it
// after an Auth::check(), because the user is set in the
// request object by the auth component after a successful
// authentication check/retrival
return response()->json($request->user());
}
// alternative method
if (($user = Auth::user()) !== null) {
// Here you have your authenticated user model
return response()->json($user);
}
// return general data
return response('Unauthenticated user');
}
This would trigger the Laravel authentication checks in the same way as auth:api guard, but won't redirect the user away. In fact, the redirection is done by the Authenticate middleware (stored in vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php) upon the failure of the authentication checking.
Beware that if you don't specify the guard to use, Laravel will use the default guard setting in the config/auth.php file (usually set to web on a fresh Laravel installation).
If you prefer to stick with the Auth facade/class you can as well use Auth::guard('api')->user() instead or the request object.
thanks to #mdexp answer
In my case I can resolve my problem with using
if (Auth::guard('api')->check()) {
$user = Auth::guard('api')->user();
}
In my controller.
I'm using Laravel 5.8. And I have created a custom Guard that is using jwt. That I use as a middleware for authenticating users.
I have some routes that need to have different responses based on being an authenticated user or an unauthenticated user. what do you suggest me to do? what is the best practices to implement this?
I can define a custom guard which its check function always returns true.and returning an integer like -1 for unauthenticated user while the user is not authenticated.but it does not sound a clean way of implementing this.
Depending on how you want to set this up, you can just use the Auth facade helpers in your controller method to see whether a user is authenticated or not:
// SomeController.php
public function index(Request $request)
{
if(Auth::guest()) {
return response()->json('i am a guest');
} else {
return response()->json('im not a guest');
}
}
or use any of the related methods:
// Inverse of `Auth::guest()`
$isLoggedIn = Auth::check();
$loggedInUser = Auth::user();
https://laravel.com/api/5.8/Illuminate/Auth/GuardHelpers.html
I have a customized LoginController with two functions:
loginCustomer that runs Auth::guard('customer')->attempt(...);
loginEmployee that runs Auth::guard('employee')->attempt(...);
I have customized two guards in config.auth that points to my two Models (Customer and Employee) and protect the routes of backoffice and frontend.
Now in my customized LogoutController i want to run Auth::logout() but it doesn't work because i think it uses the default guard.
It only works if i specify Auth::guard('customer')->logout() or Auth::guard('employee')->logout(), depending the guard that was used to login.
Is there any way to get the guard used to authenticate the user so i can use only Auth::guard($guard)->logout?
You can use shouldUse method:
After the call of this method you can logout user via guard you was previously set by shouldUse method.
In your case:
if( Auth::guard('customer')->attempt(...) ){
Auth::shouldUse('customer');
}
if( Auth::guard('employee')->attempt(...) ){
Auth::shouldUse('employee');
}
After this you can use Auth::logout and previously choosen guard (via shouldUse) will be used:
// just use Auth::logout without Auth::guard(GUARDNAME)->logout()
Auth::logout();
Short documentation about this method: https://laravel.com/api/5.4/Illuminate/Auth/AuthManager.html#method_shouldUse
This might not be the perfect solution, but it works. Basically, just go through all the guards and check if the user is authenticated by that guard. If he is - log him out. Be aware that this will log him out of all the guards he is logged in to.
This code would go to your logout controller:
$guards = array_keys(config('auth.guards'));
foreach ($guards as $guard) {
if(Auth::guard($guard)->check()) Auth::guard($guard)->logout();
}