I want when I type the address http://localhost/agendab/public or when I open my web application, it will redirect directly to login, or when I click on disconnect, it will redirect to login.
web.php
Auth::routes();
Route::resource('events', 'EventController')->middleware('auth');
loginController.php
protected $redirectTo = '/events';
public function login(Request $request)
{
$input = $request->all();
$this->validate($request, [
'name' => 'required',
'password' => 'required',
]);
$fieldType = filter_var($request->name, FILTER_VALIDATE_EMAIL) ? 'email' : 'name';
if(auth()->attempt(array($fieldType => $input['name'], 'password' => $input['password'])))
{
return redirect()->route('events');
}else{
return redirect()->route('login')
->with('error','Email-Address And Password Are Wrong.');
}
}
Http/Middleware/RedirectIfAuthenticated.php
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/events');
}
return $next($request);
}
When you use Laravel resources, you need pre-defined way to call. Ex for the index you have to call events.index, if update then events.update...
In case you're calling a custom route in the same EventsController the defied it before the resource route.
In RedirectIfAuthenticated.php
if (Auth::guard($guard)->check()) {
return redirect('/events.index');
}
or
return Redirect::route('events.index'); #using facade
return redirect()->route('events.index'); #using helper class
FYK
HTTP Redirects
Actions Handled By Resource Controller
Resource Controllers
Redirect proper route name
return redirect()->route('events.index'); // loginController.php
Related
In my project, I using laravel as api
UserController > profile() need token to run
For example when I call it without token, laravel display error which "Route [login] not defined" and it's right because we don't have any template in laravel.
How can I return json response instead redirect to login page as html?
public function profile(): JsonResponse
{
//using protected method
return response()->json($this->guard()->user());
}
So basically what you can do is you can create a customized Auth middleware which returns a JSON response.
Or you can use a simple condition in your function:
if (Auth::check()){
//if logged in user exists
} else {
//if logged in user does not exist
}
You can make middleware manually and in the middleware you can check user if exists. For example, if you use JWT token, then you can write like that as app/Http/Middleware/Authenticate.php :
public function handle($request, Closure $next, $guard = null)
{
/* Check is token filled */
if (!Auth::check()) {
return response()->json([
'success' => false,
'status' => 401,
'message' => 'Bad authorization',
'data' => []
], 401);
}
return $next($request);
}
For route partion:
Route::group([
'middleware' => 'auth'
], function () {
Route::get('/profile', 'User#profile');
});
Open Authenticate file app/Http/Middleware/Authenticate.php
add reference
use Closure;
use Illuminate\Support\Facades\Auth;
put this code:
public function handle($request, Closure $next, ...$guards)
{
if (!Auth::guard('api')->check()) {
return response()->json(['message' => 'Error Message!']);
}
return $next($request);
}
The code that you want to edit is located in app/Http/Middleware/Authenticate.php in the function redirectTo
I'm using google drive in my project for login with google.
It's working fine for me, but the problem is when user select email, in callback method user have to redirect to '/', but user will redirect to home, this is callback method :
public function callback(Request $request)
{
$googleUser = Socialite::driver('google')->stateless()->user();
$user = User::where('email', $googleUser->email)->first();
if (!$user) {
$user = User::create([
'name' => $googleUser->name,
'email' => $googleUser->email,
'password' => bcrypt(\Str::random(16))
]);
}
auth()->loginUsingId($user->id);
return $this->loggedIn($request, $user) ?: redirect(route('login'));
}
It's ok for next time user login with google, but for the first time redirect to home.
And in loggedIn function for the first time returned false because two_factor_type is off in default :
public function loggedIn(Request $request, $user)
{
if ($user->two_factor_type === 'on') {
auth()->logout();
$request->session()->flash('auth', [
'user_id' => $user->id,
'remember' => $request->has('remember')
]);
if ($user->two_factor_type === 'on') {
$code = ActiveCode::generateCode($user);
//TODO send sms
}
return redirect(route('login.twoFactor'));
}
return false;
}
Even in my LoginController or RegisterController i changed this :
protected $redirectTo = RouteServiceProvider::HOME;
To this :
protected $redirectTo = '/';
So why it will redirect to home ?
in app/Http/Controllers/Auth/LoginController check if the controller protected with middleware, e.g:
public function __construct()
{
$this->middleware('guest')->except('logout');
//meaning if there is user authenticated not guest,
//when he hit function other than logout()
//will be redirected to default landing, in code below
}
in app/Http/Middleware/RedirectIfAuthenticated will check if current auth()->user() is authenticated
change the default code to :
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/home'); // here change the default redirected
}
return $next($request);
}
please check route file maybe in route file your '/' path will return home page view like below...
Route::get('/', function ()
{
return view('welcome');
});
so please try to change this with your need.
or please remove below line from your callback function
return $this->loggedIn($request, $user)
I'm building a Laravel application from start with user login/registration function.
Below is some code of it:
// web.php
Route::middleware(['guest'])->group(function () {
Route::get('/register', 'UserController#register');
Route::post('/register', 'UserController#doRegister')->middleware('throttle:10,1');
Route::get('/login', 'UserController#login')->name('login');
Route::post('/login', 'UserController#doLogin')->middleware('throttle:15,1');
});
Route::get('/logout', 'UserController#logout');
// UserController.php
class UserController extends Controller
{
public function register()
{
return view('user.register');
}
public function doRegister(Request $request)
{
$this->validate($request, [
'name' => 'required',
'email' => 'required|email|unique:App\User',
'password' => 'required|confirmed'
]);
$userData = $request->only(['name', 'email']);
$userData['password'] = Hash::make($request->input('password'));
$user = User::create($userData);
auth()->login($user);
return redirect("/");
}
use ThrottlesLogins;
protected $maxAttempts=5;
protected $decayMinutes=1;
public function login()
{
return view('user.login');
}
public function doLogin(Request $request)
{
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
$this->validate($request, [
'email' => 'required|email',
'password' => 'required'
]);
if (auth()->attempt($request->only(['email', 'password']), $request->boolean('remember_password')) == false) {
$this->incrementLoginAttempts($request);
return back()->withErrors([
'message' => __('auth.failed')
])->with('email', $request->input('email'));
}
$this->clearLoginAttempts($request);
return redirect()->to('/');
}
protected function username()
{
return 'email';
}
public function logout()
{
auth()->logout();
return redirect()->to('/');
}
}
The web page seem working.
When I enable middleware \Illuminate\Session\Middleware\AuthenticateSession::classin Kernel.php (for trial function "Invalidating Sessions On Other Devices" later), following error happen:
After creating new user success and redirect to home page with redirect("/"), Illuminate\Auth\AuthenticationException: Unauthenticated will happen and redirect again to login page (expected must go to home page with logged user).
Stacktrace:
E:\Web\movie-resumer\vendor\laravel\framework\src\Illuminate\Session\Middleware\AuthenticateSession.php:94
Stack trace:
#0 E:\Web\movie-resumer\vendor\laravel\framework\src\Illuminate\Session\Middleware\AuthenticateSession.php(55): Illuminate\Session\Middleware\AuthenticateSession->logout(Object(Illuminate\Http\Request))
This trace refer to following code in AuthenticateSession.php:
class AuthenticateSession
{
public function handle($request, Closure $next)
{
...
if ($request->session()->get('password_hash') !== $request->user()->getAuthPassword()) {
$this->logout($request);
}
...
}
}
I just try with other replacement as below in UserController#doRegister method:
Change auth()->login($user); to use auth()->attempt($request->only(['email', 'password'])); then Exception will not occur
Or: change return redirect("/"); to use return view('home'); then Exception will not occur (the URL http://localhost/register will show the home page with logged user)
Or: change/remove the route name 'login' (Route::get('/login', 'UserController#login')->name('login123');) then Exception will not occur.
Do my first implement has any mistake, so that it cannot working with AuthenticateSession middleware?
Beware with me for a second as I try to lay the background to my issue.
So I having using the python web framework Flask close to a year now and it has a wonderful extension called Flask-Login that helps provide user session management kind of like this in laravel.
Having said all that, there is a certain feature in Flask-Login that provides the functionality that when a user is not logged or signed in and tries to access that a page that requires one to be authenticated for example /create_post, they will be redirected back to the login page with that page encoded in the query string like /login?next=%2Fcreate_post.
Am trying to implement the same feature in a laravel project that am working on so I can redirect the user to the page they probably wanted to go to in the first place or to a different route in case that query string doesn't exist and I cannot seem to find where to put my code to do just that and I don't want to mess with anything in the vendor directory(because of the obvious issues that come with that), and I have tried manipulating the file app/Http/Middleware/RedirectIfAuthenticated.php by doing what is below but with no success.
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/');
}
$previous_url = url()->previous(); // how do I insert this in query string
return $next($request);
}
Will I have to create my own middleware or is there another way of implementing this kind of feature in laravel?
NOTE: I am not using the default laravel authentication system. I have created my own controller SessionsController to handle logins which contains the below code.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class SessionsController extends Controller
{
public function __construct()
{
$this->middleware('auth')->except(['create', 'login']);
}
public function create()
{
$data = [
'title' => 'Login',
'body_class' => 'hold-transition login-page',
];
return view('auth.login', $data);
}
public function login(Request $request)
{
$this->validate($request, [
'username' => 'required',
'password' => 'required',
]);
$user = User::checkCredentials($request->username, $request->password);
if (!$user) {
return back()->with([
'class' => 'alert-danger',
'message' => 'Please check your credentials',
]);
}
// set session active flag to true
$user->session_active = true;
$user->save();
auth()->login($user);
return redirect()->route('dashboard');
}
public function destroy()
{
$user = auth()->user();
$user->last_login = date('Y-m-d H:i:s');
$user->session_active = false;
$user->save();
auth()->logout();
return redirect()->route('login')->with([
'class' => 'alert-success',
'message' => 'You logged out successfully',
]);
}
}
Thank you.
I managed to somewhat solve my issue even though I didn't use query strings as I had wanted.
I create a helper function get_previous_url as shown below
/**
* Gets the previous url
*
* #return null|string
*/
function get_previous_url()
{
$host = $_SERVER['HTTP_HOST'];
$previous_url = url()->previous();
// check if previous url is from the same host
if (!str_contains($previous_url, $host)) {
return null;
}
// get the previous url route
list(, $route) = explode($host, $previous_url);
// make sure the route is not the index, login or logout route
if (in_array(substr($route, 1), ['', 'login', 'logout'])) {
$route = '';
}
return $route;
}
And then I called the same function in my SessionsController class in the create method by doing this
public function create()
{
$previous_url = get_previous_url();
if ($previous_url) {
session(['previous_url' => $previous_url]);
}
...
}
And then I changed my login method to
public function login(Request $request)
{
...
$redirect = redirect()->route('dashboard'); // '/'
if (session()->has('previous_url')) {
$redirect = redirect(session()->pull('previous_url'));
}
return $redirect;
}
Below is some method in a trait AuthenticatesUsers where Illuminate\Foundation\Auth, Laravel.
...
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|string',
'password' => 'required|string',
]);
}
...
public function username()
{
return 'email';
}
Originally, my goal is to make another login form with user_id and password in mobile device, so this will check Auth() and if success, it will work some method and automatically logout after then. could you tell me detailed advice?
Additional question.
as Jaskaran Singh's advice I added it also as below.
protected function authenticated(Request $request, $user)
{
if($request->Inn == 'Inn') {
return redirect()->route('mobiles_start', ['Inn' => 'Inn']);
}
elseif($request->Ut == 'Ut') {
return redirect()->route('mobiles_destroy', ['Ut' => 'Ut']);
}
return view('welcome');
}
but if login failed, then it is redirected back to the /login page instead of expected view page that pre defined in the route(mobiles_start and mobiles_destroy) above.
How could I do?
You can login with User ID like this:
if(Auth::loginUsingId($user->id)){
return response()->json(['success' => $user], $this->successStatus);
}
You don't have to extend the core trait or any core Laravel code.
in app/Http/Controllers/Auth/LoginController.php add the following functions, this will override the default functions in AuthenticatesUsers trait.
add username() function
public function username()
{
if(request('id')){
return 'id'; // if request contains id then return it
}
return 'email'; // else return email
}
add validateLogin() function
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required', //remove |string
'password' => 'required|string',
]);
}
that's it.