I am working in laravel framework. I have two type of login
Ajax base login
Simple form submit login
When I submit my simple login form then user login successfully, but when I login user via ajax request then I receive success response of login but when I submit another form after ajax login then it redirect me to simple login page for login because of user Auth not set properly in ajax login.
Here is middleware
public function handle($request, Closure $next, $guard = null) {
if (Auth::check()) {
return $next($request);
}
return redirect()->route('userLogin');
}
Controller method
public function ajaxPostLogin($inputs) {
try {
$inputs = $this->validateInputs($inputs, RulesHelper::$user_login, RulesHelper::$user_login_msg);
$inputs["user_type"] = 'user';
$response = $this->getObj(UserHelper::class)->ajaxUserLogin($inputs);
if (isset($response["success"])) {
echo json_encode(["success" => true, 'token' => csrf_token()]);
die;
} else {
echo json_encode(["success" => false, 'error' => $response]);
die;
}
} catch (\Exception $ex) {
echo json_encode(["success" => false, "message" => $ex->getMessage()]);
die;
}
}
I don't know that where I am doing mistake. Guide in a right way.
Thanks
In Laravel. After you Authenticate user via AJAX, dont echo any response. Echo only on errors. Not on success. This helped me as well.
Related
After a user registers and logs in, I have an unlisted page/secret page that I need to protect with another password.
I'm trying to get spatie/laravel-littlegatekeeper to help me do this, but running into issues getting it working.
What I'm doing:
littlegatekeeper .config:
<?php
return [
// Login credentials
'username' => env('GATEKEEPER_USERNAME', 'default_username'),
'password' => env('GATEKEEPER_PASSWORD', 'default_password'),
// The key as which the littlegatekeeper session is stored
'sessionKey' => 'littlegatekeeper.loggedin',
// The route to which the middleware redirects if a user isn't authenticated
// 'authRoute' => url('login'),
];
Routes:
Route::get('/secretapage', ['middleware' => 'littlegatekeeper', function () {
return view('dir.secretapage.index');
}]);
Route::get('/secretapage/login', function () {
return view('dir.secretapage.login');
});
Route::post('/secretapage/login/addCredentials', 'SecretController#addCredentials')->name('addCredentials');
SecretController:
After I log in my user. I then try to access the URL /secretpage I get redirected back to the homepage rather the /secretpage/login
public function index(Request $request)
{
$auth = resolve('littlegatekeeper');
if($auth->isAuthenticated())
{
return view('dir.secretpage.index');
}
return view('dir.secretpage.login');
}
///// FOR LOGING IN
public function addCredentials(Request $request)
{
$auth = resolve('littlegatekeeper');
$loginSuccess = $auth->attempt($request->only([
'username',
'password'
]));
if ($loginSuccess) {
return redirect('/secretapage')->with('success', 'Thank You for authorizing. Please proceed.');
}
else{
return back()->with('error', 'You entered the wrong credentials');
}
}
Blade login file:
<form method="POST" action="{{ route('addCredentials') }}">
...
</form>
If I access secretpage/login 1st, I'm able to add the username and password.
Then I can get into /secretpage with no issues....
But I really need to have the users go to /secretpage 1st then if not logged in with the secret username/pass get redirected to /secretpage/login.
I found some help on Laracasts and this ended up working.
Change the authRoute in the littlegatekeeper config file to the following
'authRoute' => '/secretpage/login',
Suppose I have a page A where auth middleware is being used. Because of no login it gets redirected to login page.
On login page I have custom ajax login system. On succesful login I want to redirect to page A with same url so that action can be completed.
My code for login is like this:
public function postLogin(Request $request)
{
$auth = false;
$errors = [];
$inputs = $request->all();
$validator = $this->validator($inputs);
if ($validator->fails()) {
return response()->json([
'auth' => false,
'intended' => URL::previous(),
'errors' => $validator->errors()
]);
}
$user = User::where('email', $request->get('email'))->first();
if ($user && $user->is_active == 0) {
$errors[] = "This account has been deactivated";
} else if ($user && $user->confirm_token != null) {
$errors[] = "Please verify your email in order to login";
} else {
$credentials = ['email' => $request->get('email'), 'password' => $request->get('password'), 'is_active' => 1];
if (Auth::attempt($credentials, $request->has('remember'))) {
$auth = true;
} else {
$errors[] = "Email/Password combination not correct";
}
}
if ($request->ajax()) {
return response()->json([
'auth' => $auth,
'intended' => URL::previous(),
'errors' => $errors
]);
}
return redirect()->intended(URL::route('dashboard'));
}
I am trying to get previous url through url()->previous() but it returns login page url. Can someone guide me in this please. Any improvements/help will be appreciated.
I am using Laravel 5.4
I have a very similar problem here: Ajax Auth redirect on Laravel 5.6
As #aimme (https://stackoverflow.com/users/1409707/aimme) pointed out, Ajax calls are stateless, so basically you can't interact with backend.
His suggestion and my suggestion is to pass in the URL the intended page to redirect to, or maybe in your case you could to it via post parameters, e.g.:
return response()->json([
'auth' => false,
'intended' => $request->intended,
'errors' => $validator->errors()
]);
There is no need to do anything special for AJAX calls.
Redirect the same way you normally would on the back-end after a form submission.
return redirect()->route('dashboard');
On the front-end you just need to be sure that you use the redirected URL to change the window.location. This will cause the browser to refresh and go to the new page.
axios.post(url, formData).then(response => {
window.location = response.request.responseURL;
});
This code snippet is for the popular Axios library but the same thing can be done with jQuery or vanilla JavaScript.
It might help you
Instead of these return redirect()->intended(URL::route('dashboard'));
use
return redirect('dashboard');
Laravel 5.4 + support . not know for lower version
return redirect()->back();
This will redirect to previous page from where you came .
Ajax part
<script type="text/javascript">
var url = "<?php echo url()->previous(); ?>";
location.href = url;
</script>
OR simply javascript function
history.go(-1);
Check for above and working fine for me please check for your code .
If I understand your problem correctly, the problem is that you're confusing the previous URL for the intended URL when you're trying to provide a URL to redirect to in your JSON response. The previous URL actually refers to the HTTP Referrer, not the intended URL, which is set in the session by Laravel's auth middleware.
The HTTP referrer is the page that initiates a request. If you are currently on page /foo and you click a link to a page /bar, the HTTP Referrer on /bar will be /foo. The same thing happens when you initiate an AJAX request, the page you're on will be the referrer of the end point you're hitting. In your case your login page is initiating the request to your login handler, via AJAX.
When you try to visit a page protected by Laravel's auth middleare, it is at that point Laravel sets a value for the intended URL in the session, before redirecting you to the login page. Laravel stores the intended URL in the session as url.intended (As you will be able to see in Illuminate\Routing\Redirector::intended, which is what redirect()->intended() calls). So all you need to do is grab that from the session.
if ($request->ajax()) {
return response()->json([
'auth' => $auth,
'intended' => session()->pull('url.intended') ?: URL::route('dashboard'),
'errors' => $errors
]);
}
return redirect()->intended(URL::route('dashboard'));
Note: Using ->pull will remove the item from the session after it has been retrieved.
An easier way to do this would be just to grab the target URL from an intended RedirectResponse:
$redirect = redirect()->intended(URL::route('dashboard'))
if ($request->ajax()) {
return response()->json([
'auth' => $auth,
'intended' => $redirect->getTargetUrl(),
'errors' => $errors
]);
}
return $redirect;
I solved it by making a hidden field in form containing url()->previous() value because no other way I was getting previous page i.e Page A url. I tried almost all above answers.
URL::previous();
this method will help you get previous URL. and you can redirect user to there using jQuery somelike this:
window.location.href = url; // <- you can try your url here.
Good Luck !!
First of all when you got a request in backend save the redirect()->intended();
intended() checks if the session index url.intended exists and
redirects to it by default or else redirect to $default='/' which can
be overwritten.
then pass this URL when request success, example:
function testAjax(handleData) {
$.ajax({
url:"getvalue.php",
success:function(data) {
window.location.href = data.url;
}
});
}
If a user creates a conference with id "2" he should be allowed to access "proj.test/conference/manage/2".
But a user that did not create the conference with id "2" should be redirected to the login page if he is not authenticated. If he is authenticated should be redirected to the homepage.
But its not working properly, if the user created the conference with id 2 he can access "proj.test/conference/manage/2" but other user that did not create this conference if accesses "proj.test/conference/manage/2" it appears an error:
This action is unauthorized.
So instead of redirecting the user to the homepage it shows this error. Do you know why is not working?
I have the store method, after storing the conference the user is redirected to the management area to manage that specific conference, for example, to manage the conference with id 2 the user is redirected to "proj.test/conference/manage/2".
Store method:
public function store(Request $request)
{
$this->validate($request, [
'conference_name' => 'required|max:255|string',
...
]);
$conference = Conference::create([
'name' => $request->conference_name,
...
]);
}
Then in the AuthServiceProvider I add:
public function boot(GateContract $gate)
{
$this->registerPolicies();
$gate->define('access-management-area', function($user, $conference)
{
return $user->id == $conference->conference_creator_id;
});
}
And in the manage method I have:
public function manage($id){
$conference = Conference::findOrFail($id);
if($this->authorize('access-management-area', $conference)){
return view('conferences.manage')->with('myconference',$conference);
}
else{
return redirect('/home');
}
}
Do not use $this->authorize as it does not work the same as Gate::allows()/denies().
The authorize method will throw an exception if it fails, it will not return false for the sake of conditional comparison.
From the docs:
If the action is not authorized, the authorize method will throw an Illuminate\Auth\Access\AuthorizationException, which the default Laravel exception handler will convert to an HTTP response with a 403 status code.
So, instead, use Gate::denies for comparisons.
if(Gate::allows('access-management-area', $conference)) {
return view('conferences.manage')->with('myconference',$conference);
} else {
return redirect('/home');
}
I am creating a login check function. But my two flash data messages are not setting correct.
If user has logged on and then if the session expires it should set this
flash data message Your session token has expired!
And if the user has not logged on and tries to access a controller with out logging on
then it should set this flashdata message You need to login to
access this site!
For some reason it is always showing the second flashdata message.
Question: How am I able to use the two flashdata messages properly.
Controller: Login.php
Function: check
public function check() {
$uri_route = basename($this->router->directory) .'/'. $this->router->fetch_class();
$route = isset($uri_route) ? $uri_route : '';
$ignore = array(
'common/login',
'common/forgotten',
'common/reset'
);
if (!in_array($route, $ignore)) {
// $this->user->is_logged() returns the user id
if ($this->user->is_logged()) {
// $this->session->userdata('is_logged') returns true or false
if (!$this->session->userdata('is_logged')) {
// Redirects if the user is logged on and session has expired!
$this->session->set_flashdata('warning', 'Your session token has expired!');
redirect('admin/common/login');
}
} else {
$this->session->set_flashdata('warning', 'You need to login to access this site!');
redirect('admin/common/login');
}
}
I run function via codeigniter hook that way I do not have to add it on every controller.
$hook['pre_controller'] = array(
'class' => 'Login',
'function' => 'check',
'filename' => 'Login.php',
'filepath' => 'modules/admin/controllers/common'
);
What are you trying to check via the uri() is actually a very bad way of checking, also you should include login checks as a construct function not single.. here is what your function should look like:
function __construct()
{
parent::__construct();
if (!$this->session->userdata('logged_in')) {
// Allow some methods?
$allowed = array(
'some_method_in_this_controller',
'other_method_in_this_controller',
);
if (!in_array($this->router->fetch_method(), $allowed)
{
redirect('login');
}
}
}
I'm getting this TokenMismatchException with Laravel 4. It happens to me if the browser sits on the login page for a while. For example a lot of times when I come back to work on my project the next day, if my browser has the login page open in a tab, when I try to log in I get the TokenMismatchException. If I'm logging in and out throughout the day while working, I never see it. It's like the token expires or something.
Route.php
// route to show the admin login form
Route::get('login', array('uses' => 'AdminController#showLogin'));
// route to process the admin login form
Route::post('login', array('uses' => 'AdminController#doLogin'));
AdminController.php
public function showLogin()
{
// show the login form
return View::make('admin.login');
}
public function doLogin()
{
// validate the info, create rules for the inputs
$rules = array('username' => 'required','password' => 'required' );
// run the validation rules on the inputs from the form
$validator = Validator::make(Input::all(), $rules);
// if the validator fails, redirect back to the form
if ($validator->fails()) {
return Redirect::to('login')
->withErrors($validator) // send back all errors to the login form
->withInput(Input::except('password')); // send back the input (not the password) so that we can repopulate the form
} else {
// create our user data for the authentication
$userdata = array('my_username'=> Input::get('username'),'password'=> Input::get('password'));
// attempt to do the login
if (Auth::attempt($userdata)) {
return Redirect::intended('dashboard');
} else {
// Authentication not successful, send back to form
return Redirect::to('login')->with('message', 'Your username/password combination was incorrect');
}
}
}
Please, help is needed...
That's normal, session will expire if you get idle for too long. It's a security measure, so you just need to make sure you redirect your user to login when the token expires. Add this to your global.php file or create a exceptions.php file to it:
App::error(function(\Illuminate\Session\TokenMismatchException $exception)
{
return Redirect::route('login')->with('message','Your session has expired. Please try logging in again.');
});