Auth->user() don't work in API controller in Laravel - laravel

In my api.php file, I have apiResource
Route::apiResource('temperature', App\Http\Controllers\Api\TemperatureController::class);
In TemperatureController in store method, I try create new Temperature:
use Illuminate\Support\Facades\Auth;
public function store(CreateTemperatureRequest $request){
Temperature::create([
'temperature' => $request->get('temperature'),
'userName' => Auth()->user()->name,
'created_at' => Carbon::now()
]);
return true;
}
After the form submits, I have an error - Trying to get property 'name' of non-object. My form is vueJs component.
If I add auth middleware in the controller:
public function __construct()
{
$this->middleware('auth:api')->only('store');
}
and call Auth('api')->user()->name,
I have error 401 (Unauthorized).
I am not using Passport for authentication. I use standard Laravel authentication, but the form is a Vue component and I use an API controller.
How can I get user data in the API controller?

use auth() instead
auth($guard)->user()->name
$guard may be
'api' or 'web'

try
request()->user();
when working with API, You must send a header with you, this is working fine with sanctum. if it doesnt work switch to laravel Sanctum

Related

First Party use of Laravel Passport

I'm using Laravel Passport for API authentication,
This is my stack:
ReactJs (front-end)
Laravel (backend - API)
Currently I'm giving Personal Access Tokens directly to users like this, and after getting the token user's can access protected routes as usual:
public function login(LoginRequest $request)
{
$request->authenticate(); // it authenticate the user based on $request->email and $request->password
/** #var User $user */
$user = Auth::user();
$token = $user->createToken('auth');
return response([
'message' => 'success',
'user' => $user,
'token' => $token->accessToken,
]);
}
It works fine but the problem is now, anyone can get their token directly using tools like Postman, and use that token to access protected routes. which I don't want.
I only want the users to access the routes via my whitelisted frontends. like Reactjs SPA etc..
I read some articles sugesting to whitelist our domains on config/cors.php, it works for modern browsers, but still tools like postman would work. :(
Is there any-way I can acheive this?
Thank you so much for reading.
https://laravel.com/docs/9.x/passport#consuming-your-api-with-javascript you can check that part of the docs. I think you can protect your api with that middleware solution

Problem with using laravel Auth::logoutOtherDevices

I want to use Laravel Auth::logoutOtherDevices. I added \Illuminate\Session\Middleware\AuthenticateSession::class to $middlewareGroups => web in kernal.
When I use this in login function :
public function login(Request $request)
{
Auth::attempt([
'email' => $request->input('email'),
'password' => $request->input('password')
], $request->has('remember'));
Auth::logoutOtherDevices($request->input('password'));
}
All passwords in my database change and I can't login with other accounts. :| Where is the problem?
Before getting started, you should make sure that the Illuminate\Session\Middleware\AuthenticateSession middleware is present and un-commented in your App\Http\Kernel class' web middleware group:
'web' => [
// ...
\Illuminate\Session\Middleware\AuthenticateSession::class,
// ...
],
Then, you may use the logoutOtherDevices method provided by the Auth facade. This method requires the user to confirm their current password, which your application should accept through an input form
use Illuminate\Support\Facades\Auth;
Auth::logoutOtherDevices($currentPassword);
You should have sendLoginResponse method after attempt as it is inside of AuthenticateUsers trait, because sendLoginResponse implements $request->session()->regenerate(); in it.
A clean implementation of your purpose is to leave trait's login method intact and create authenticated method in the controller that has AuthenticateUsers trait and add below code it in.
protected function authenticated(Request $request, $user)
{
Auth::logoutOtherDevices($request->get('password'));
}

How can I make my middleware respond with a json object if I use an API route

I'm building my first API with Laravel and I'm using JWT for authentication. I don't really understand guards all that well yet but I think I managed to guard my User class. So when I try to reach a route in my UserController it get's guarded and the Authenticate middleware gets called if the user is no authenticated. The problem is that when I try to use the API route via Postman that I get the following error
ErrorException: Header may not contain more than a single header, new line detected in file
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
protected function redirectTo($request)
{
if (!$request->expectsJson()) {
return response()->json(['message' => 'Unauthorized'], 403);
}
}
}
api.php
<?php
use Illuminate\Support\Facades\Route;
Route::post('register', 'AuthController#register');
Route::get('user/{id}', 'UserController#index');
You could use:
abort(response()->json('Unauthorized', 403));
Try this
Route::group(['middleware' => 'auth:api'], function(){
// Put your authenticated routes here
});

Laravel Passport post route test on postman

I set up Laravel Passport and started to create a few Get routes to get some data, that worked fine.
Now I am trying to post to get on auth token, which currently does not work:
This is my route which I call (Get route works, Post route does not work):
Route::group(['middleware' => 'auth:api'], function ()
{;
Route::get('users', ['as' => 'users', 'uses' => 'ApiController#users']);
Route::post('login/{id}/{name}', ['as' => 'login', 'uses' => 'ApiController#login']);
});
The method in my ApiController looks currently like this:
public function login(Request $request, $id, $name)
{
if($request->isMethod('post'))
{
$id = $request->id;
$name = $request->name;
$inquiry = new Inquiry();
$inquiry->user_id = $id;
$inquiry->user_name = $name;
if($inquiry->save())
{
return redirect()->route('inquiry.index')->with('success', 'Success.');
}
else
{
return redirect()->route('inquiry.index')->with('error', 'An error accured.')->withInput();
}
}
else
{
dd("Use Post.");
}
}
I tried to call it with following options:
Edit
I somehow managed to get this work after many hours, but still dont understand something.
First I did following:
public function callback(Request $request)
{
dd($request->code) // this holds a token I need for the code parameter in the post
...
With that I could get the token for the code parameter, but I think there is a better way to do that.
And finally this is now how I get the access + refresh token:
But there has to be a better way to get the code token of the callback request ($request->code), instead of dumping it and copying it.
The problem is that you have your login route inside a route group with auth:api on it. This means the user needs to be authenticated to even be able to authenticate. Just remove the login route outside the group and you should be fine.
You should call the Passport::routes method within the boot method of your AuthServiceProvider. This method will register the routes necessary to issue access tokens and revoke access tokens, clients, and personal access tokens:
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
/oauth/authorize route is already defined by the Passport::routes method. You do not need to manually define this route.

Redirect to login when user is not connect

When i want to access to a page in my application i get an exception when i'm not logged in
ErrorException in ec75fc198343b0a46e649467428bd2d5f829caf1.php line 49:
Trying to get property of non-object
Should i make a route middleware group ?
I would like when i want to access to the pages when i'm not logging that the app redirect me directly to the login form without display me this error message !
Someone know how to do that ?
Enable the auth middleware for the action that is responsible for rendering the page. There are multiple ways how you can accomplish this in Laravel. Here are a few of them:
In the routes file for a particular action
Route::get('your/page', ['middleware' => 'auth', 'uses' => 'YourPageController#index']);
or the same thing fluently
Route::get('your/page', 'YourPageController#index')->middleware('auth');
In the routes file for a group of actions/pages
Route::group(['middleware' => ['auth'], function () {
Route::get('your/page', 'YourPageController#index');
});
In the controller
class YourPageController extends Controller
{
public function __construct()
{
$this->middleware('auth'); // you can pass an array of actions/methods that should not be covered by the auth middleware in a second parameter ['except' => 'someaction']
}
}
Edit your Kernel.php and add this to the protected $routeMiddleware part at the end:
'auth' => \App\Http\Middleware\Authenticate::class,
Then in your routes you can use this 'auth' to check if the user is logged in.
For example:
Route::get('/example', 'YourController#getExample')->middleware('auth');
if you don't have a middleware or you have any trouble follow this https://laravel.com/docs/5.4/authentication
Include the Middleware in routes.
Route::get('/Demo','DemoLine#index')->middleware('auth');

Resources