I am running a Laravel project on Windows and Ubuntu. On Ubuntu, authentication doesn't work. When I entered the correct username and password, I was directed to the home page (route with the name login). However, on Windows it can run well, which is directed to the dashboard page.
LoginController.php
class LoginController extends Controller
{
public function index(){
return view('login');
}
public function authenticate(Request $request)
{
$credentials = $request->validate([
'username' => 'required',
'password' => 'required',
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'username' => 'The provided credentials do not match our records.',
'password' => 'The provided credentials do not match our records.',
]);
}
}
web.php
Route::get('/home', function () {
return view('home');
})->name('login');
Route::get('/login', [LoginController::class, 'index'])->middleware('guest');
Route::post('/login', [LoginController::class, 'authenticate']);
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard')->middleware('auth');
In Windows i use XAMPP (PHP 8.2.1) and Laravel 9.42. In Ubuntu i use PHP 8.1.7 and Laravel 9.42 without XAMPP. How to fix this on Ubuntu?
https://laravel.com/docs/9.x/authentication#authenticating-users
I think there is any cache issue, just run the following commands and check it.
php artisan optimize:clear
Related
Using https://laravel.com/docs/9.x/sanctum , I'm try create API application.
Generating token is ok.
But when I try to restrict my endpoint to authorized users with middleware, any check permission didn't work, endpoint is accessible for all.
In controller I tested with debug auth('sanctum')->check() - and I became true for valid token and false else.
My routes/api.php
Route::post('login', [AuthController::class, 'login']);
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::post('logout', [AuthController::class, 'logout']);
Route::group([
'prefix' => 'services/{service}',
'where' => [
'service' => implode('|', array_column(ServiceEnum::cases(), 'name'))
]],
function () {
Route::get('accounts/{account}/balance', [AccountController::class, 'getBalance']);
});
});
It was my fail.
I recreate a project with new fresh laravel (something was broken with installing laravel passport) and then solve a problem with empty auth user in constructor of controller:
public function __construct(Request $request)
{
$this->middleware(function ($request, $next) {
$this->user = auth()->user();
return $next($request);
});
}
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.
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
I want to disable access to register route without login in laravel 8. I am using laravel jetstream with livewire.
Here is code in routes\web.php. I have not changed anything in route file.
Route::get('/', function () {
return view('welcome');
});
Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
To disable registration go to config/fortify.php and comment out Features::registration().
'features' => [
//Features::registration(),
Features::resetPasswords(),
// Features::emailVerification(),
Features::updateProfileInformation(),
Features::updatePasswords(),
Features::twoFactorAuthentication(),
],
it work with Fortify you can control its appearance in
`config/fortify.php Features::registration(),
you can customize the register logic validation ... from App\Actions\Fortify CreatesNewUsers
There are several similar questions but all of them seem incomplete as they are referring to not existing functions.
I am referring to:
Check for active user state with laravel
Login only if user is active using Laravel
extend laravel 5 built-in authentication to login only "if user == active"
In all of them there are presented solutions mostly to alter functions from AuthController, however those functions are not there.
I am using latest version of Laravel (5.2) so my default mentioned file looks like: https://github.com/laravel/laravel/blob/master/app/Http/Controllers/Auth/AuthController.php
Now, how do I implement this functionality? I have tried copying public function postLogin() (as suggested in those other mentioned posts) into that AuthController file. Nothing changed.
I am clearly missing something here.
Please someone help!
Edit:
The function that I have added is:
public function postLogin(Request $request)
{
$this->validate($request, [
'email' => 'required|email', 'password' => 'required',
]);
$credentials = $this->getCredentials($request);
// This section is the only change
if (Auth::validate($credentials)) {
$user = Auth::getLastAttempted();
if ($user->active) {
Auth::login($user, $request->has('remember'));
return redirect()->intended($this->redirectPath());
} else {
return redirect($this->loginPath()) // Change this to redirect elsewhere
->withInput($request->only('email', 'remember'))
->withErrors([
'active' => 'You must be active to login.'
]);
}
}
return redirect($this->loginPath())
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
]);
}
Most functionality in AuthController is added using traits. Note this line in the beginning of the class:
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
If you look at AuthenticatesAndRegistersUsers you can see that it does have a postLogin method.
As of why implementing this method doesn't work: I think you are missing the $request parameter in the method signature.
Add a larger code snippet to your question if this isn't the case.
EDIT: for future debugging: php artisan route:list gives you a list of which routes call which methods. This can give you a hint to which method to override.
So, for everyone facing the same problem on Laravel 5.2 with Authentication provided by php artisan make:auth.
First important thing is to understand that Route::auth(); points to login function and not postLogin(Thank you #lagbox!)
Then you will have to update AuthController:
Add on top of the file:
use Auth;
use Illuminate\Http\Request;
Add somewhere after use AuthenticatesAndRegistersUsers, ThrottlesLogins; :
/**
* Where to redirect users if login is unsuccessufull.
*
* #var string
*/
protected $loginPath = '/login';`
And the updated login function:
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required|email', 'password' => 'required',
]);
$credentials = $this->getCredentials($request);
// This section is the only change
if (Auth::validate($credentials)) {
$user = Auth::getLastAttempted();
if ($user->active) {
Auth::login($user, $request->has('remember'));
return redirect()->intended($this->redirectPath());
} else {
return redirect($this->loginPath) // Change this to redirect elsewhere
->withInput($request->only('email', 'remember'))
->withErrors([
'active' => 'You must be active to login.'
]);
}
}
return redirect($this->loginPath)
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
]);
}
Then login.blade.php should be updated to show the new error #if ($errors->has('active'))
Thank you guys for help!