How to customization redirection in laravel jetstream - laravel

i run the laravel jetstream and set to livewire not vue . i usually using auth ui and custom the login in
App -> Http -> controller -> auth -> LoginController
in this LoginController i custom this redirect like this
protected function authenticated(Request $request, $user)
{
if ( $user->isUser() ) {// do your margic here
return redirect()->route('user_dashboard');
}
elseif ($user->isSarpras()) {
return redirect()->route('admin_sarpras_dashboard');
}
}
but on laravel jetstream iam cant found Controller->auth . how to do best manage login and create multiple login using laravel jetstream ?

Found here: https://talltips.novate.co.uk/laravel/laravel-8-conditional-login-redirects
Create a folder under app\Http called Responses
Create a file LoginResponse.php
<?php
namespace App\Http\Responses;
use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
class LoginResponse implements LoginResponseContract
{
public function toResponse($request)
{
// below is the existing response
// replace this with your own code
// the user can be located with Auth facade
return $request->wantsJson()
? response()->json(['two_factor' => false])
: redirect()->intended(config('fortify.home'));
}
}
Make Laravel use our new Response Class
This new class now replaces the Singleton previously registered by Fortify.
Edit the JetstreamServiceProvider in your app\Providers folder;
In the boot method, add reference to your new response class. When login completes (and the user is actually Authenticated) then your new response will be called.
public function boot()
{
$this->configurePermissions();
Jetstream::deleteUsersUsing(DeleteUser::class);
// register new LoginResponse
$this->app->singleton(
\Laravel\Fortify\Contracts\LoginResponse::class,
\App\Http\Responses\LoginResponse::class
);
}
Two Factor Authentication
If you use 2FA with Jetstream, you will also need to catch the TwoFactorLoginResponse. Use the same approach;
// register new TwofactorLoginResponse
$this->app->singleton(
\Laravel\Fortify\Contracts\TwoFactorLoginResponse::class,
\App\Http\Responses\LoginResponse::class
);
You can return the same response, or create an additional response if you want different behaviour for users that login using 2FA.

Jetstream uses Fortify to power authentication.
Currently, Fortify doesn't have a way to customize redirects.
There is an open issue requesting this bahavior here: https://github.com/laravel/fortify/issues/77
There is a good chance this will be added soon!
Edit
Now you can customize the redirects via config/fortify.php:
'redirects' => [
'login' => 'dashboard',
'logout' => 'home',
'password-confirmation' => null,
'register' => 'dashboard',
'email-verification' => null,
'password-reset' => null,
],
If you need advanced customization of this behavior check out the docs here.

Related

Change LogIn route

I am working in Laravel auth application and when my user is log out I want to redirect it to custom static page and from there I want to redirect to login page again by clicking button on that page.
For example when user is trying to access some particular route, and he is unauthorized then I want to redirect with satatic.blade.php and from there I want to redirect it to log in page, How can I make it happen?
As you didn't mention which Laravel version you are using and which scaffolding you are using, I am assuming you are using Laravel 5.5/6 with LaravelUI/default auth scaffolding.
You should have App\\Http\\Controllers\\Auth namespace where you kept all auth related controller.
You should have one LoginController.php which contains all default login behavior inside AuthenticatesUsers trait. We should override the login method inside our controller.
Copy this code to your LoginController class to do so.
public function login(Request $request)
{
$this->validateLogin($request);
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
// Here is our custom logic check occurs before login
if ($this->userIsnotAuthorized()) { // All your logic checks are inside 'userIsnotAuthorized()' method. Use any function or static check here
return redirect()->to('/static/page'); // Also can use route name / url
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
EDIT #1
If you want to have the same check for all protected routes, you should generate a middleware with php artisan make:middleware CheckResourceAccessMiddleware and use the same in your route.
In CheckResourceAccessMiddleware's handle method
// Here is our custom logic check occurs before login
if ($this->userIsnotAuthorized()) { // All your logic checks are inside 'userIsnotAuthorized()' method. Use any function or static check here
return redirect()->to('/static/page'); // redirect to static page which indicates unauthorized user note
}
return $next($request); // proceed to your page as user is authorized
to register the middleware edit your app/Http/Kernel.php and add this line to $routeMiddleware array
protected $routeMiddleware = [
...
'resource_access' => \App\Http\Middleware\CheckResourceAccessMiddleware::class,
];
After this step., you can use the middleware in any routes you want to protect
Route::get('/protected', [Controller::class, 'method'])->middleware('resource_access');
OR
// Middleware will be applied to all routes inside it
Route::middleware('resource_access')->group(function () {
Route::get('/protected', [Controller::class, 'method']);
// all other protected routes will be here
});
I found different approaches for this problem, Later I Found the best solution, as mention below,
In App\Middlewear\Authenticate.php, I have to change from return route('login');
to return route('my_custom_page_route');
From my custom page I can redirect it to auth login page easily.
Thank you everyone who suggest the best solutions.

Laravel 8 jetstream stack inertia. Redirect to Home after Login, instead of users choice

What happens to me is that if the user puts the url: project.test/med, the system redirects to Login but then it does not redirect to dashboard but to med. In RedirectIfAuthenticated the expression Auth::guard($guard)->check() is not evaluated or at least in the Log it is not shown, so I am not able to identify what is happening.
/** RedirectIfAuthenticated.php */
public function handle($request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
   Log::info($request);
   Log::info(Auth::user());
foreach ($guards as $guard) {
     Log::info(Auth::guard($guard)->check());
     Log::info(Auth::check());
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
      }
   }
  Log::info(Auth::check());
   Log::info('end');
return $next($request);
 }
/** web.php */
Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
return Inertia\Inertia::render('Dashboard');
})->name('dashboard');
Route::middleware(['auth:sanctum','verified'])->get('/med', function (Request $request) {
return Inertia\Inertia::render('Med');
})->name('med');
Go to config/fortify.php and modify this line:
'home' => RouteServiceProvider::HOME,
to:
'home' => function(){
//if you want to go to a specific route
return route('dashboard');
//or if you have a bunch of redirection options
if (Auth::user()->hasRole('admin')) {
return route('admin.dashboard');
}
else{
return route('guest.dashboard');
}
}
EDIT: Fortify now ships with a simpler way of doing this. See this answer for simplified way.
The RedirectIfAuthenticated middleware does not do what you think it does. This middleware checks to see if a user is authenticated when trying to access a route with the guest middleware attached to it. So after you login to the application and you try to access /login route, this middleware will intercept the request and redirect the user to the RouteServiceProvider::HOME path.
With that being said, at the time of this writing, Laravel Fortify does not offer the ability to easily modify where the user gets redirected after registering or logging in to the application. See issue for more info
To get this to work you will have to go through a few steps.
Step 1 - Create new LoginResponse class
Anywhere in your application create a LoginResponse class and implement Laravel\Fortify\Contracts\LoginResponse.
<?php
namespace App\Http\Responses;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
class LoginResponse implements LoginResponseContract
{
/**
* #inheritDoc
*/
public function toResponse($request)
{
return $request->wantsJson()
? response()->json(['two_factor' => false])
: redirect()->intended(config('fortify.home')); // This is the line you want to modify so the application behaves the way you want.
}
}
Step 2 - Override the default Fortify Login Response
In this step you have to tell Laravel to use your login response instead of the default Fortify response.
<?php
namespace App\Providers;
use App\Http\Responses\LoginResponse;
use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
class FortifyServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(
LoginResponseContract::class, // Contract is required in order to make this step work.
LoginResponse::class,
);
}
//...
}
Once you're done making the changes the user will be redirected to wherever you set it to be.
There is a simpler solution to this.
If you look in config/fortiy.php you will see the home variable is set to:
'home' => RouteServiceProvider::HOME,
This refers to a public const variable in app/Providers/RouteServiceProvider.php
So to redirect users to the home page after they login you can simply change the home variable:
public const HOME = '/';
Doing it this way is slightly less complex and saves you having to create a whole new login response class.
If the changes don't take effect straight away try running:
php artisan optimize
Just open fortify in the config folder
Search for 'home' => RouteServiceProvider::HOME
and replace it but your code logic and don't forget to add Auth facades
use Illuminate\Support\Facades\Auth;
like is :
'home' => function () {
$is_active = Auth::user()->is_active;
$role = Auth::user()->role;
if ($is_active == 1) {
if ($role== 1) {
return '/admin/dashboard';
} else {
return '/';
}
} else {
return '/login';
}
},

Laravel - 403 invalid signature on email verification

I have enabled Email verification on my laravel site.
If they dont do it immediatly, but after a day or two, the link times out.. and they land on a page with 403-invalid signature.
From there they cannot do anything else beside manually editing the link. this is the point where I already lost some registrations. Is there a way to:
a) make this timeout much longer
b) in case of timeout/error land on a page that actually makes sense to the user?
#Omer YILMAZ answears your "a)" call and I am answearing your "b)" call:
We should disable signed Middleware that validates the URL signature (expiration) and automatically shows 403 page for the verification route, and then we should create a custom logic to validate the URL signature doing whatever we would like if it is invalid (expired).
Laravel 5.7, 5.8, 6.x and 7.x
Changing Auth\VerificationController provided by Laravel:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\VerifiesEmails;
class VerificationController extends Controller
{
use VerifiesEmails {
verify as verifyTrait;
}
protected $redirectTo = '/';
public function __construct()
{
$this->middleware('auth');
// $this->middleware('signed')->only('verify'); <-- remove this: it is causing 403 for expired email verification URLs
$this->middleware('throttle:6,1')->only('verify');
}
public function verify(Request $request)
{
if (!$request->hasValidSignature()) {
// some custom message
}
else {
return $this->verifyTrait($request);
}
}
}
Laravel 8.x
Changing the example provided by Laravel:
use Illuminate\Foundation\Auth\EmailVerificationRequest;
use Illuminate\Http\Request;
Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
if (!$request->hasValidSignature()) {
// some custom message
}
else {
$request->fulfill();
return redirect('/home');
}
})->middleware(['auth', /*'signed' <-- remove this*/])->name('verification.verify');
In laravel 5.8 or above add this lines to config/auth.php
'verification' => [
'expire' => 525600, // One year in minutes
],
The following solution worked for me. Go to the next folder, app/Http/Middleware, and edit the following file TrustProxies.php. Change protected $proxies; edit for the following protected $proxies = ‘*’;
namespace App\Http\Middleware;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
protected $proxies = '*';

Implementing native multi auth (user vs admin) using guards in Laravel 5.5 - guest middle ware uses hard coded named route

I would like to implement native multi authentication in my application for two types of users: User and Admin.
I started implementing a new admins table migration (by copying the existing create_users_table).
I created a new model called Admin (by copying the existing User model)
Both (User and Admin) models were updated to specify which guards they use like this:
User Model
protected $guarded = ['user'];
Admin Model
protected $guarded = ['admin'];
Then I setup the auth configuration like this:
config/auth.php
https://pastebin.com/iLAZbX2z
Then I defined my custom auth routes for users and admins like this:
routes/web.php
https://pastebin.com/raw/CKX9Xddb
Finally, I defined the auth protected routes for the two user types like this:
routes/web.php
// User auth protected pages
Route::prefix('manage')->middleware('auth:user')->namespace('Manage')->group(function() {
Route::get('/', 'DashboardController#index');
});
// Admin auth protected pages
Route::prefix('admin')->middleware('auth:admin')->namespace('Admin')->group(function() {
Route::get('/', 'DashboardController#index');
});
I tested the user login first before proceeding (there's more to be done to get admin to login), by going into http://myapp.local/login and entering my credentials and I was successfully redirected to user's dashboard (i.e. http://myapp.local/manage). All of the user specific functionality (e.g. reset pass) etc.. are all working fine).
However; when testing the guest middleware by visiting http://myapp.local/manage directly, I expected to be redirected to http://myapp.local/login but got an error instead:
Route [login] not defined.
This error is valid; because in the routes definition, I've named the user login as user.login
It looks like the guest middleware uses a hard coded named route called login in the unauthenticated exception handler.
vendor\laravel\framework\src\Illuminate\Foundation\Exceptions\Handler.php
protected function unauthenticated($request, AuthenticationException $exception)
{
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest(route('login')); // <------
}
How can I tell the guest middleware to use a differently named route for the login (when un-authenticated user tries to visit a auth protected page)?
I will need to use this later for the admin guest middleware also.
Thanks to Sohel0415's answer; I realised that the App\Exceptions\Handler extends the vendor\laravel\framework\src\Illuminate\Foundation\Exceptions\Handler.php, which means I can solve it like this:
I've edited the app\Exceptions\Handler.php like this:
Included this use statement at the top:
use Illuminate\Auth\AuthenticationException;
Added this method:
https://pastebin.com/raw/10Y1tS6d
I've named the user login as user.login
You're getting the error because the route name is user.login and you're trying to use login route. So, use proper route name here:
redirect()->guest(route('user.login'));
Use Request::is() to check the requested url, then redirect :
protected function unauthenticated($request, AuthenticationException $exception)
{
if(\Request::is('manage/*')){
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest(route('user.login'));
}
else if(\Request::is('admin/*')){
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest(route('admin.login'));
}
else{
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest(route('login'));
}
}
Note: add this method in App\Exceptions\Handler

Laravel 5.2 Authentication Redirect with Parameters

Since, I was not able to find any question like this in SO, I am writing this post hoping this is not a duplicate...
I have a page developed using KnockoutJs which I am using to protect via Laravel Authentication. Basically, I am using Laravel only for the purpose of login/registration and once the user logs/signs in, he is redirected to the KnockoutJS page.
Now lets just say I have a URL,
http://example.com/mypage#q=some+parameters&p=somethingsomething
If I share that URL with one of my friends, it obviously redirects my friend to the Login Page. Now, the login page URL (where he is redirected to) is
http://example.com/login#q=some+parameters&p=somethingsomething
But once he logs in, he is being redirected to
http://example.com/mypage#
Which obviously is not right, because I need the parameters to be there...
My Routes page is as follows,
Route::group(['middleware' => 'web'], function() {
Route::auth();
Route::get('/', 'MainController#index')->name('home.index');
});
Route::group(['middleware' => ['web','auth']], function () {
Route::get('/mypage', 'MyController#index')->name('mypage.index');
});
And my AuthController has the redirectTo Url set
protected $redirectTo = '/mypage';
What change should I do (in AuthController, or in Routes? Or in a MiddleWare) to redirect the user to
http://example.com/mypage#q=some+parameters&p=somethingsomething
after login?
You can use the intended method in Laravel.
eg:
public function authenticate()
{
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Authentication passed...
return redirect()->intended('dashboard');
}
}
This will redirect the user to the intended URL to the login page or if there is no intended URL, then to dashboard.
https://laravel.com/docs/5.2/authentication#authenticating-users
Since Laravel's Redirect::intended did not work for me, I am posting the answer to this question myself...
User Jquery/Javscript to create cookies after redirection like this :
(function(){
'use strict';
var intended = window.location.hash;
(intended.length > 0) ? jQuery.cookie('intended', '/app' + intended) : jQuery.cookie('intended', '/app');
})();
and make these changes into Laravel 5.2's default AuthController
//Replace the default constructor with this
public function __construct(Request $request) {
if(isset($_COOKIE['intended'])) {
$this->setRedirect($request);
}
}
//Copy paste it anywhere in your AuthController Class
protected function setRedirect($request) {
$intended = (url($_COOKIE['intended']));
$url['intended'] = $intended;
$request->session()->put('url', $url);
}
Hope this helps someone....
Thanks, :)

Resources