I am trying to check if the user is active then redirect it to the application and if the user is not active then keep the user on login page saying "your account has been disabled or you dont have a valid account. Please contact your admin". I am done with the whole application but this is the only thing I cant be able to understand. I tried it Handler.php, tried writing postLogin(), getLogin() functions, changed the route too but still cant be able to figure out. This authentication method of laravel is so confusing as we dont know where the functions are. Any help would be much appreciated.
Routes
// Route::auth();
Route::get('auth/login', 'Auth\AuthController#getLogin');
Route::post('auth/login', 'Auth\AuthController#postLogin');
Route::get('auth/logout', 'Auth\AuthController#getLogout');
AuthController
In postLogin() I am just checking whether it goes in to the function or not but it not going in either of the functions if I comment out route::auth()
public function postLogin(Request $request)
{
echo "getting in this function";
}
public function getLogin($id)
{
echo "getting in to this function";
$users = User::find($id);
if($users->is_active == 1) {
return redirect()->intended('dashboard');
} else {
Session::flash("message", "Authentication failed. Please contact your admin.");
return redirect('/login');
}
}
For this, first I would suggest to use Laravel's default route and controllers for authentication and then amend it as per the need.
This will surely work:
routes/web.php
Route::auth();
Http/Controllers/Auth/LoginController.php
public function login(Request $request)
{
$email = $request->input('email');
$password = $request->input('password');
$remember = $request->input('remember') ? true : false;
if ($user = Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
if(Auth::user()->is_active == 1) {
return redirect()->intended('dashboard');
} else {
Auth::logout();
Session::flash("message", "Authentication failed. Please contact your admin.");
return redirect('/login');
}
} else {
return $this->sendFailedLoginResponse($request);
}
}
Related
I have a page with a some content on it and a comments section. Comments can only be left by users who are signed in so I have added a login form to the page for users to sign in with (this only shows if they are not already logged in).
The problem I have is that when the user signs in they get redirected back to the home page and not the page they were previously on.
I have not changed the login method from the out of the box set-up.
Can anyone suggest a simple way to set the redirect url. My thoughts are that it would be good to be able to set it in the form.
Solution for laravel 5.3:
In loginController overwrite the showLoginForm() function as this one:
public function showLoginForm()
{
if(!session()->has('url.intended'))
{
session(['url.intended' => url()->previous()]);
}
return view('auth.login');
}
It will set the "url.intended" session variable, that is the one that laravel uses to look for the page which you want to be redirected after the login, with the previous url.
It also checks if the variable has been set, in order to avoid the variable to be set with the login url if the user submit the form with an error.
For Laravel 5.5, following code worked for me by just updating LoginController.php
public function showLoginForm()
{
session(['link' => url()->previous()]);
return view('auth.login');
}
protected function authenticated(Request $request, $user)
{
return redirect(session('link'));
}
Please use redirect()->intended() instead in Laravel 5.1
You can also see more about it here: http://laravel.com/docs/5.1/authentication
For Laravel 5.3
inside App/Http/Controllers/Auth/LoginController
add this line to the __construct() function
$this->redirectTo = url()->previous();
So the full code will be
public function __construct()
{
$this->redirectTo = url()->previous();
$this->middleware('guest', ['except' => 'logout']);
}
It works like a charm for me i'm using laravel 5.3.30
For Laravel 5.4, following code worked for me by just updating LoginController.php
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\URL;
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
Session::put('backUrl', URL::previous());
}
public function redirectTo()
{
return Session::get('backUrl') ? Session::get('backUrl') : $this->redirectTo;
}
The Laravel 5.6, When user insert wrong credentials then login page will reload and session(['link' => url()->previous()]); will take login URL in link variable. So the user will redirect to a login page again or redirect to /home if login success. So to avoid these below code working for me! After that no matter how much time user insert wrong credentials he will redirect after login to exactly where he was before login page.
Update or overwrite public function showLoginForm() in LoginController.
public function showLoginForm()
{
if (session('link')) {
$myPath = session('link');
$loginPath = url('/login');
$previous = url()->previous();
if ($previous = $loginPath) {
session(['link' => $myPath]);
}
else{
session(['link' => $previous]);
}
}
else{
session(['link' => url()->previous()]);
}
return view('auth.login');
}
Also, Update or Overwrite protected function authenticated(Request $request, $user) in LoginController.
protected function authenticated(Request $request, $user)
{
return redirect(session('link'));
}
If you want to redirect always to /home except for those pages with comments, then you should overwrite your redirectTo method in your LoginController:
public function redirectTo()
{
return session('url.intended') ?? $this->redirectTo;
}
On all pages where you want to remain on the site, you should store the url for one request in the session:
public function show(Category $category, Project $project){
// ...
session()->flash('url.intended' , '/' . request()->path());
}
Redirect to login with the current's page url as a query string:
login
In your LoginController check if exists and save the query string in session then redirect to the url after login
public function __construct() {
parent::__construct();
if ( \request()->get( 'redirect_to' ) ) {
session()->put( 'redirect.url', \request()->get( 'redirect_to' ) );
}
$this->middleware( 'guest' )->except( 'logout' );
}
protected function authenticated(Request $request, $user) {
if(session()->has('redirect.url') {
return redirect( session()->get( 'redirect.url' ) );
}
}
Look into laravel cheat sheet
and use:
URL::previous();
to go to the previous page.
Laravel 5
(maybe 6 also, not tested, if someone knows it please update the answer)
add this to LoginController:
protected function redirectTo(){
return url()->previous();
}
Note: if present the field $redirectTo , remove it
in your RedirectIfAuthenticated.php change this code
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect()->intended('/contactus');
}
return $next($request);
}
please notice to :
return redirect()->intended('/contactus');
Inside your template file you can just use:
{{ url()->previous() }}
To redirect from the controller you should use
return redirect()->back();
or Just
return back();
use Illuminate\Support\Facades\Redirect;
public function Show_Login_Form()
{
$back = Session::put('url_back',url()->previous());
$current = url()->current();
if(Session::get('user_id'))
{
if ($back == $current) { // don't back Login Form
return Redirect::to('home');
}
elseif (Session::has('url_back')) {
return Redirect::to('home');
}
else{
return redirect()->back();
}
}
else{
if ($back == $current) {
return Redirect::to('home');
}
else{
Session::put('url_back',url()->previous());
}
return view('account.customer-account.login');
}
}
public function signin_user(Request $request) // Login post
{
$username = $request->input_username_login;
$password = md5($request->input_password_login);
$result = DB::table('tbl_user')
->where([['user_email',$username],['user_password',$password]])
->orWhere([['user_phone',$username],['user_password',$password]])
->first();
if($result){
Session::put('user_id', $result->user_id );
Session::put('user_name', $result->user_name);
Session::put('user_username', $result->user_username);
Session::put('user_avatar', $result->user_avatar);
return Redirect::to(Session::get('url_back')); // Back page after login
} else {
Session::put('message_box', 'Error !!!');
return redirect()->back();
}
}
You can use redirect back with Laravel 5:
<?php namespace App\Http\Controllers;
use Redirect;
class SomeController extends Controller {
public function some_method() {
return Redirect::back()
}
}
Use Thss
return Redirect::back('back-url')
I was trying to do the change password using API Laravel. But it didn't work. I'm new to API Laravel.
Any suggestion to solve my problem?
public function __construct()
{
$this->middleware('auth');
}
public function store(ChangePasswordValidation $request)
{
if(Auth::check($data['current_password'], $user->password))
{
$user = User::find(Auth::user()->id)->update(["password"=> bcrypt($request->password)]);
$success['token'] = $user->createToken('newToken')->accessToken;
return response()->json(['success' => $success], 200);
}
else
{
return response()->json(['error'=>'Unauthorised'], 401);
}
}
the result shown in Postman is:
{
"message": "Unauthenticated."
}
You need to use guard as you are using API
so change
Auth::user()
To
Auth::user('api')
also
$this->middleware('auth');
To
$this->middleware('auth:api');
Edit this line
if(Auth::check($data['current_password'], $user->password))
Into
if(Auth::check($request['current_password'], $user->password))
I'm currently using 2 projects. 1 front end (with laravel backend to communicate with API) and another laravel project (the API).
Now I use Laravel Passport to authenticate users and to make sure every API call is an authorized call.
Now when I want to log out my user, I send a post request to my API (with Bearer token) and try to log him out of the API (and clear session, cookies,...)
Then on the client I also refresh my session so the token is no longer known. Now when I go back to the login page, it automatically logs in my user. (Or my user is just still logged in).
Can someone explain me how to properly log out a user with Laravel passport?
Make sure that in User model, you have this imported
use Laravel\Passport\HasApiTokens;
and you're using the trait HasApiTokens in the User model class using
use HasApiTokens
inside the user class.
Now you create the log out route and in the controller,
do this
$user = Auth::user()->token();
$user->revoke();
return 'logged out'; // modify as per your need
This will log the user out from the current device where he requested to log out. If you want to log out from all the devices where he's logged in. Then do this instead
$tokens = $user->tokens->pluck('id');
Token::whereIn('id', $tokens)
->update(['revoked'=> true]);
RefreshToken::whereIn('access_token_id', $tokens)->update(['revoked' => true]);
Make sure to import these two at the top
use Laravel\Passport\RefreshToken;
use Laravel\Passport\Token;
This will revoke all the access and refresh tokens issued to that user. This will log the user out from everywhere. This really comes into help when the user changes his password using reset password or forget password option and you have to log the user out from everywhere.
You need to delete the token from the database table oauth_access_tokens
you can do that by creating a new model like OauthAccessToken
Run the command php artisan make:model OauthAccessToken to create the model.
Then create a relation between the User model and the new created OauthAccessToken Model , in User.php add :
public function AauthAcessToken(){
return $this->hasMany('\App\OauthAccessToken');
}
in UserController.php , create a new function for logout:
public function logoutApi()
{
if (Auth::check()) {
Auth::user()->AauthAcessToken()->delete();
}
}
In api.php router , create new route :
Route::post('logout','UserController#logoutApi');
Now you can logout by calling posting to URL /api/logout
This is sample code i'm used for log out
public function logout(Request $request)
{
$request->user()->token()->revoke();
return response()->json([
'message' => 'Successfully logged out'
]);
}
Create a route for logout:
$router->group(['middleware' => 'auth:api'], function () use ($router) {
Route::get('me/logout', 'UserController#logout');
});
Create a logout function in userController ( or as mentioned in your route)
public function logout() {
$accessToken = Auth::user()->token();
DB::table('oauth_refresh_tokens')
->where('access_token_id', $accessToken->id)
->update([
'revoked' => true
]);
$accessToken->revoke();
return response()->json(null, 204);
}
I am using Laravel 6.12.0, below function is working for me.
public function logout(Request $request){
$accessToken = Auth::user()->token();
$token= $request->user()->tokens->find($accessToken);
$token->revoke();
$response=array();
$response['status']=1;
$response['statuscode']=200;
$response['msg']="Successfully logout";
return response()->json($response)->header('Content-Type', 'application/json');
}
This is my first post.. and i find a clean solution (Laravel last Version)
/**
* Logout api
*
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
if (Auth::check()) {
$token = Auth::user()->token();
$token->revoke();
return $this->sendResponse(null, 'User is logout');
}
else{
return $this->sendError('Unauthorised.', ['error'=>'Unauthorised'] , Response::HTTP_UNAUTHORIZED);
}
}
Below is the simplest way I found to do it.
1. USE database SESSION INSTEAD OF file SESSION
Official documention
php artisan session:table
php artisan migrate
Replace SESSION_DRIVER=file by SESSION_DRIVER=database in your .env file.
2. DELETE USER SESSION RIGHT AFTER LOGIN
After a user is redirected to your frontend and logs in to finally get a token, you probably call a route in api/routes.php to get the user information, that's where I'm closing the user backend session before sending back user information to the frontend:
Route::middleware('auth:api')->get('/user', function (Request $request) {
// Close user session here
Illuminate\Support\Facades\DB::table('sessions')
->whereUserId($request->user()->id)
->delete();
return $request->user();
});
3. REVOKE TOKENS AT LOGOUT
Then, to "log out" (actually, revoke tokens) the user from the frontend, you just need to call another route to revoke the token and refresh_token:
Route::middleware('auth:api')->post('/logout', function (Request $request) {
// Revoke access token
// => Set oauth_access_tokens.revoked to TRUE (t)
$request->user()->token()->revoke();
// Revoke all of the token's refresh tokens
// => Set oauth_refresh_tokens.revoked to TRUE (t)
$refreshTokenRepository = app('Laravel\Passport\RefreshTokenRepository');
$refreshTokenRepository->revokeRefreshTokensByAccessTokenId($request->user()->token()->id);
return;
});
You may prefer to put these two closures in the UserController.
Hope help someone:
if (Auth::check()) {
$request->user()->tokens->each(function ($token, $key) {
$token->delete();
});
}
Good Luck.
I use this in my project to logout from multiple device.
public function logout(Request $request, $devices = FALSE)
{
$this->logoutMultiple(\Auth::user(), $devices);
return response()->json([], 204);
}
private function logoutMultiple(\App\Models\User $user, $devices = FALSE)
{
$accessTokens = $user->tokens();
if ($devices == 'all') {
} else if ($devices == 'other') {
$accessTokens->where('id', '!=', $user->token()->id);
} else {
$accessTokens->where('id', '=', $user->token()->id);
}
$accessTokens = $accessTokens->get();
foreach ($accessTokens as $accessToken) {
$refreshToken = \DB::table('oauth_refresh_tokens')
->where('access_token_id', $accessToken->id)
->update(['revoked' => TRUE]);
$accessToken->revoke();
}
}
Try this code to help you to logout from passport authentication.
Route::post('/logout', function(){
if (Auth::check()) {
Auth::user()->AauthAcessToken()->delete();
}
return response()->json([
'status' => 1,
'message' => 'User Logout',
], 200);
});
check whether your model contains OauthAccessToken which needs to connect with the database oauth_access_tokens. The access token is stored in the database table oauth_access_tokens. and makes a relation from users to oauth_access_tokens.
public function AauthAcessToken(){
return $this->hasMany(OauthAccessToken::class);
}
You can use following code to remove to token for logged in user.
$request->user()->token()->revoke();
If you want to learn about this in-depth then watch this tutorial:
https://www.youtube.com/watch?v=UKSQdg1uPbQ
public function logout(Request $request)
{
$request->user()->token()->revoke();
if ($request->everywhere) {
foreach ($request->user()->tokens()->whereRevoked(0)->get() as $token) {
$token->revoke();
}
}
return response()->json(['message' => 'success']);
}
I am using Laravel 5.3, I have a situation here...I'm on PAGE-2 and logged-out from there then redirected to Login Page. Now, what I am trying to achieve is to redirect back to PAGE-2 if the user logs-in again.
the Current situation is that, the user will be redirected to defaultAfterLogin page, which is not my desired login flow.
NOTE: Default page after-login is "DashBoard".
It is OKAY IF YOU WILL GO THE FIRST-TIME TO PAGE-2(not the default DashBoard page) and if you're not LOGGED-IN you will be redirected to LOGIN PAGE then IF YOU'll login again you will be redirected back to PAGE-2, which is fine.
BUT what is happening now is that, when you're in PAGE-2 then you LOGOUT then you will be REDIRECTED TO LOGIN-PAGE, if you LOGIN again you will be redirected to "DashBoard" which is not what I want. It should redirect back to PAGE-2
The flow should be,... users will be redirected after login no matter which PAGE they're previously working with.
Here's the a sample script I am using (it's actually from laravel i'am using its built-in Auth)
protected function handleUserWasAuthenticated(Request $request, $throttles)
{
if ($throttles) {
$this->clearLoginAttempts($request);
}
if (method_exists($this, 'authenticated')) {
return $this->authenticated($request, Auth::guard($this->getGuard())->user());
}
return redirect()->intended($this->redirectPath());
}
Any ideas, please? Thank you very Much for your help.
Try this
On auth middleware:app/http/middleware/RedirectIfAuthenticated
// redirect the user to your login page "/login"
public function handle($request, Closure $next)
{
if ($this->auth->check()) {
return redirect('/login');
}
return $next($request);
}
// This is your login method
public function postSignIn(Request $request)
{
$request_data = $request->all();
$email = $request_data['email'];
$user_details = User::where('email', $email)->first();
if(count($user_details) > 0)
{
$credentials = array('email'=> $email ,'password'=> $request_data['password']);
if ($this->auth->attempt($credentials, $request->has('remember')))
{
return redirect()->to('/dashboard'); //Here is your redirect url, redirect to dashbord
OR
return redirect()->to('/page2'); //Here is your redirect url, redirect to page2
}
else
{
$error = array('password' => 'Please enter a correct password');
return redirect()->back()->withErrors($error);
}
}
else
{
$error = array('password' => 'User not found');
return redirect()->back()->withErrors($error);
}
}
Open AuthController class : app/Http/Controllers/Auth/AuthController.php
Add below property to the class
protected $redirectAfterLogout = 'auth/login';
you can change auth/login with any url.
U CAN USE THIS CODE
return redirect()->back();
or
u can use route and in ur route u need to configure and in controller u can put the below code
// this is ur route
Route::get('/dashboard',[
'uses' => 'PostController#dashboard',
'as' => 'dashboard',
'middleware' => 'auth'
]);
//put this in ur controller
return redirect()->route('dashboard');
i was using laravel bcrypt authentication in a back end application but client asked plain password authentication so that he can see the password of each user as administrator. My whole app logic is on laravel inbuilt authentication method an bcrypt hashing. how can i replace it to authenticate with plain password mach stored in database instead of storing hash ?
class AuthController extends Controller
{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
public function __construct()
{
$this->middleware('guest', ['except' => ['getLogout', 'getLogin']]);
}
public function postLogin()
{
$data = \Request::all();
$rules = [
'email' => 'required|email|max:255|exists:users',
'password' => 'required|exists:users'
];
$validator = \Validator::make($data, $rules);
if ($validator->fails()) {
//login data not exist in db
return redirect('/login')->withErrors($validator)->withInput();
} else {
$email = Request::input('email');
$pass = Request::input('password');
//in my table users, status must be 1 to login into app
$matchWhere = ['login' => $email, 'password' => $pass, 'status' => 1];
$count = \App\User::where($matchWhere)->count();
if ($count == 1) {
$user = \App\User::where($matchWhere)->first();
Auth::loginUsingId($user->id);
return redirect()->intended('/');
} else {
//not status active or password or email is wrong
$validator->errors()->add('Unauthorized', 'Not accepted in community yet');
return redirect('/login')->withErrors($validator)->withInput();
}
}
}
public function getLogin()
{
if (Auth::check()) {
return redirect()->intended('/');
} else {
return view('auth.login');
}
}
public function getLogout()
{
Auth::logout();
return redirect()->intended('/login');
}
}
If you are now using Laravel 5^, you can do that by searching for the class Illuminate/Auth/EloquentUserProvider and do some minor tweaks in there.
For e.g. find the public function retrieveByCredentials() and validateCredentials(). In the second function, you can see that the laravel is checking the hashed passwords to be fed into Auth::attempt() method. Just change it to plain checking and you are done.
public function retrieveByCredentials(array $credentials)
{
if (empty($credentials)) {
return;
}
// First we will add each credential element to the query as a where clause.
// Then we can execute the query and, if we found a user, return it in a
// Eloquent User "model" that will be utilized by the Guard instances.
$query = $this->createModel()->newQuery();
foreach ($credentials as $key => $value) {
if (! Str::contains($key, 'password')) {
$query->where($key, $value);
}
}
return $query->first();
}
/**
* Validate a user against the given credentials.
*
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #param array $credentials
* #return bool
*/
public function validateCredentials(UserContract $user, array $credentials)
{
$plain = $credentials['password'];
return $this->hasher->check($plain, $user->getAuthPassword());
}
Change $this->hasher->check to normal check and you will be done. :)
In laravel 4 you could have rewritten the HASH module . This stackoverflow thread explains how to use SHA1 instead of bycrypt [ check the accepted answer and comments ] .
You can make use of the method explained here and save your password without hashing .
Well, that really compromises your client's website security.
Storing plain passwords in the DB is not recommended at all. If someone gained access to the database his/her site will be really vulnerable, anyone with a copy of the database would have easy access to all kind of accounts. I insist you should create a reset/change password functionality instead of storing plain passwords in the DB.
Anyway, you could just get the plain password with
$password = Input::get('password');
And I guess you could authenticate users with
if (Auth::attempt(array('password' => $password)))
{
return Redirect::route('home');
}
Wow, these are all so complicated, it's as simple as.
if ($user = User::where('email', request()->email)->where('password', request()->password)->first()) {
Auth::login($user);
return redirect()->to('/');
}
Though I do agree that in a production environment you should not do this. But I can see for some applications if the users are aware the passwords are stored in plain text it may be ok.