Laravel Auth::check() is always failing - php

I am building a ReactJS App with a Laravel 8.9.0 backend api. I am using the Laravel Auth functionality that creates a token and passes it to my front end app. I am able to log-in and create a token properly with a hash password etc. What I am not able to do is "Check Login" with the is_login method shown below in the controller. The Auth::check() is always failing, what am I doing wrong? Below are my controllers and routes api.php file. Please help!
Login Controller:
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\Users;
class LoginController extends Controller
{
public function login(Request $request) {
$login = $request->validate([
'email' => 'required:string',
'password' => 'required:string'
]);
if(!Auth::attempt($login)) {
return response([
'message' => 'Invalid Credentials'
]);
}
$accessToken = Auth::user()
->createToken('authToken')
->accessToken;
return response([
'user' => Auth::user(),
'access_token' => $accessToken
]);
}
public function is_login()
{
$is_login = false;
if (Auth::check()) {
$is_login = true;
}
return response()->json(['is_login' => $is_login]);
}
}
Routes api.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::post('/login', 'App\Http\Controllers\LoginController#login');
Route::get('/login-check', 'App\Http\Controllers\LoginController#is_login');

To fix this problem you must pass the token into the header with every request:
In my ReactJS I did this on componentDidMount()
componentDidMount() {
try {
const config = {
headers: {
Authorization: `Bearer ${mytoken}`
}
};
axios.get('/api/login-check',
{ key: "value" },
{ headers: config }
).then(
console.log('succ')
).catch(
console.log('err')
);
} catch (err) {
console.log('Error in submission', err)
}
}
and in my api I added the middleware to the check:
Route::middleware('auth:api')->get('/login-check', 'App\Http\Controllers\LoginController#is_login');

Related

laravel Auth::login($user) always return 401 Unauthorized

I'm a newbie in laravel. I work with a simple blog with angular and laravel. I use Sanctum for authorization and registration.
This is my code AuthController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Auth;
use Validator;
use App\Models\User;
class AuthController extends Controller
{
public function register(Request $request)
{
$validator = Validator::make($request->all(),[
'name' => 'required|string|max:255|unique:users',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8'
]);
if($validator->fails()){
return response()->json($validator->errors());
}
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password)
]);
$token = $user->createToken('auth_token')->plainTextToken;
Auth::login($user);
return response()
->json(['result' => 'success']);
}
public function login(Request $request)
{
if (!Auth::attempt($request->only('name', 'password')))
{
return response()
->json(['message' => 'Unauthorized']);
}
$user = User::where('name', $request['name'])->firstOrFail();
$token = $user->createToken('auth_token')->plainTextToken;
return response()
->json(['message' => 'Authorized']);
}
// method for user logout and delete token
public function logout()
{
auth()->user()->tokens()->delete();
return response()->json([
'message' => 'You have successfully logged out and the token was successfully deleted'
]);
}
}
web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\MainController;
use App\Http\Controllers\StoryController;
use App\Http\Controllers\AuthController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', [MainController::class, 'home']);
Route::get('/about', [MainController::class,'about']);
Route::get('/review', [MainController::class,'review'])->name('review');
Route::post('/review/check', [MainController::class,'review_check']);
/*Route::get('/about/{id}/{name}', function ($id,$name) {
return "ID:".$id." Name:".$name;
});*/
Auth::routes();
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
//Route::post('/api/saveStory', [StoryController::class,'store']);
Route::apiResource('api/saveStory', 'StoryController');
//Route::resource('/api/story', 'StoryController');
Route::post('api/register', [AuthController::class, 'register']);
//API route for login user
Route::post('api/login', [AuthController::class, 'login']);
//Protecting Routes
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::post('api/user-information', function(Request $request) {
return auth()->user();
});
// API route for logout user
Route::post('api/logout', [AuthController::class, 'logout']);
});
This work fine. But when i'm success login and send post request angular to 'api/user-information' i always get error '401 Unauthorized'.
angular 2 request:
loginMethod()
{
this.http.post(this.baseUrl+"api/login", this.loginForm).subscribe(
(data:ResponseLogin)=>{
this.responseLogin=data;
if(this.responseLogin.message ==='Authorized')
{
this.router.navigate(['/user-profile']);
}
console.log("this.responseLogin.message:"+this.responseLogin.message);
},
error => console.log(error)
);
}
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::post('api/user-information', function(Request $request) {
return auth()->user();
});
But when I send request 'api/user-information' using Postman, I'm success get data authorized user.
Please help me resolve this problem.
First, you have to send your authorization token too with your request. You are sending request to protected endpoint. Laravel has middleware to check if the user authenticated or not. If you try to send a request to /about it shouldn't be a problem but you are sending request to route that has protected with middleware.

Laravel - API login authentication check

As part of learning Laravel API, login and authentification I've created API login route which which works fine, user is loged-in and JSON response returns token that needs to be put into Bearer Token field and API resource movies route which allows CRUD operations.
I'm using Postman for testing and when I go directly to GET /api/movies route without login or pasting token into Bearer Token I cannot access this route which is desired outcome if user is not authenticated and got this message:
Symfony\Component\Routing\Exception\RouteNotFoundException: Route [login] not defined. in file /home/****/Projects/movie-api/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php on line 444
What I'm trying to do, instead of this message to return JSON response that user is not authenticated but don't know how or where to put that code.
I've tried with Auth:check() in api.php and in my AuthController, but could not make it work and could not find anything in Laravel documentation regarding this.
This is my api.php and AuthController.php:
api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\API\MovieController;
use App\Http\Controllers\API\AuthController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::post('register', [AuthController::class, 'signup']);
Route::post('login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function() {
Route::resource('movies', MovieController::class);
});
AuthController.php
<?php declare(strict_types=1);
namespace App\Http\Controllers\API;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use Validator;
use App\Models\User;
use App\Providers\MovieApiProvider\ApiResponseServiceProvider as ApiResponseService;
class AuthController extends Controller
{
private ApiResponseService $apiResponseService;
public function __construct()
{
$this->apiResponseService = new ApiResponseService;
}
public function signup(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
'confirm_password' => 'required|same:password',
]);
if ($validator->fails()) {
return $this->apiResponseService->responseError('Error validation', ['error' => $validator->errors()]);
}
$input = $request->all();
$input['password'] = bcrypt($input['password']);
$user = User::create($input);
$success['token'] = $user->createToken('MyAuthApp')->plainTextToken;
$success['name'] = $user->name;
return $this->apiResponseService->responseSuccess($success, 'User created successfully.');
}
public function login(Request $request)
{
if (Auth::attempt([
'email' => $request->email,
'password' => $request->password
])) {
$authUser = Auth::user();
$success['token'] = $authUser->createToken('MyAuthApp')->plainTextToken;
$success['name'] = $authUser->name;
return $this->apiResponseService->responseSuccess($success, 'User signed in');
} else {
return $this->apiResponseService->responseError('Unauthorised.', ['error' => 'Unauthorised'], 401);
}
}
}
Can someone help with this?
Laravel assumes you are using a browser, so when checking authentication, you are redirected to a login page. All you need is:
Accept: application/json

Laravel 5.8 - How to handle API route with optional auth?

Can anyone help me to handle API route with optional Auth check? I have an API ROUTE 'apply-coupon' which can be used by both 'Guest' and 'Logged In' user. I need to get User ID in controller if the user is logged in.
Front end - Is developed with React JS, on 'Apply Coupon' button click, an API is calling as -
API end point - https://example.com/api/apply-coupon
Request payload - {coupon : 'my-coupon-code', shop_id : '1', subtotal : '150'}
Note : No token is passed in the header, since 'apply coupon' feature is available for guest user as well.
Expected output :- When user clicks on 'Apply Coupon' it should return User ID, if user id logged in.
Following is my route in api.php file -
Route::post('/apply-coupon', [
'uses' => 'CouponController#applyCoupon',
]);
Update :- And the default guard is -
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
I have tried
if(Auth::user()) {
dd(Auth::user());
}
and
auth()->guard('api')->user()
But nothing worked. Thanks!!
I don't think you can "optionaly" protect routes. What I think you could do is check in your controller if the user is authenticated and if it is, then get its ID. Of course the route should be unprotected
use Illuminate\Support\Facades\Auth;
...
function applyCoupon() {
if (Auth::check()) {
// The user is logged in...
// return Cupon + Auth::id()
} else {
// Not logged in code
// return Cupon
}
}
docs
Add one middleware ValidateUser.php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use Tymon\JWTAuth\Facades\JWTAuth;
class ValidateUser
{
public function handle($request, Closure $next)
{
if (! $request->bearerToken()) {
return $next($request);
}
return $this->validateToken($request, $next);
}
private function validateToken($request, Closure $next)
{
try {
if (! JWTAuth::parseToken()->authenticate()) {
throw new \Exception('Unable to find the account');
}
} catch (TokenExpiredException $e) {
throw new \Exception('Token has been expired');
} catch (TokenInvalidException $e) {
throw new \Exception('Token is not valid');
} catch (JWTException $e) {
throw new \Exception('Unable to parse the token');
}
return $next($request);
}
}
In your http/kernel.php in
$routeMiddleware
add
'api.auth.validate' => \App\Http\Middleware\ValidateUser::class
Now in your api.php you can use middleware to check it something like:
middleware(['api.auth.validate'])

Dingo "Unauthenticated" error message for logged In users in laravel 5.5

I'm using [Dingo/api][1] laravel package to create an API. I worked with it before and I have not this problem.
this is my routes in the api.php file:
$api = app('Dingo\Api\Routing\Router');
$api->version('v1', ['prefix' => 'v1', 'namespace' => 'App\Http\Controllers'], function ($api) {
$api->group(['prefix' => 'auth'], function ($api) {
$api->post('signIn', 'Auth\LoginController#signIn');
});
$api->group(['middleware' => 'api.auth'], function ($api) {
$api->get('signOut', ['uses' => 'Auth\LoginController#signOut']);
$api->get('test', function () {
return response()->json(['foo' => 'bar']);
});
});
});
/signIn route works fine and respond a token that can used in other protected endpoint like /test and /test directory works fine.
But I want to Sign out a user and call /signOut route it responses this always:
{
"success": false,
"message": "Unauthenticated.",
"status_code": 500
}
This is signOut method in LoginController :
public function signOut()
{
//return 'Hiiiii Alll';
try {
$token = \Tymon\JWTAuth\Facades\JWTAuth::getToken();
\Tymon\JWTAuth\Facades\JWTAuth::invalidate($token);
return [
'success' => true,
'message' => 'You Signed Out Successfully'
];
} catch (\Exception $e) {
return $this->response->error('Something went wrong', 404);
}
}
Even when I return a Simple string from that method it does not run, seems problem is in ['middleware' => 'api.auth'] that I used But if it's right why problem does not occurred for test directory that in in the same route group?
Update(solution) :
I found that should change logout to SignOut in __construct() method in LoginController method :
public function __construct()
{
$this->middleware('guest')->except('logout');
}

JWT custom authentication in Laravel 5

i have made a custom model class for authentication in Laravel 5. I already changed the auth.php and jwt.phpattributes that represents User class.
The JWT is working, but, when i try to login it returns the invalid credentials error, even when i have the register in my database.
I've been thinking it should be something about encryptation, so i tried to encrypt my password and i have updated with the hash de password field in DB (it wasn't encrypted yet). But it stills bring me the credentials error.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\AuthRequest;
use App\Http\Requests;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
class AuthController extends Controller
{
public function login(AuthRequest $request) {
$credentials = [
'email' => $request->input('email'),
'password' => bcrypt($request->input('password'))
];
try {
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 401);
}
} catch (JWTException $e) {
return response()->json(['error' => 'could_not_create_token'], 500);
}
return response()->json(['token' => $token]);
}
}
Someone knows how i can solve this problem?
I've solved this. It was a problem between my stored password and my parameter password. I took off the bcrypt and put the field encrypted in database.

Categories