LARAVEL 5: Need to keep query string after auth redirects - authentication

I have a link I am sending via email. For example, www.swings.com/worker?id=3382&tok=jfli3uf
In this case I want the person to click the link, get sent to the login page(which it does) and then be directed to a controller method WITH the $id and $tok variables. I can't get that part to work. Any ideas? I am only using the RedirectIfAuthenticated class and this is what it looks like:
public function handle($request, Closure $next)
{
$user = $request->user();
if ($this->auth->check()) {
if($user && $user->hasRole('worker'))
{
return redirect('worker');
}
return redirect('home');
}
return $next($request);
}
hasRole is a method I created in the User model that checks the role of the logged in user

You can flash data to the session when redirecting by chaining the with() method:
// in your handle() method:
return redirect('home')->with($request->only('id', 'tok'));
// then in home controller method:
$id = session('id');
$tok = session('tok');

AFTER SOME HOURS I WAS ABLE TO HAVE A SOLUTION:
ReturnIfAuthenticated wasn't changed. I just added the following within my controller that this link should go to:
for instance, the route would be:
Route::get('worker', 'WorkerController#methodINeed');
Within this method:
public function methodINeed() {
$id = Input::get('id');
$tok = Input::get('tok');
// Do what I need this variables to do
}
What I didn't understand and what could not be properly understood is that the auth controller in Laravel 5 is triggered when a user is a guest it will still redirect to the actual method with all its original data once auth is successful. Hope this is helpful.

Related

Problems on testing middleware in Laravel with Clousure $next

I have this middleware on my app that checks the user role for a route:
public function handle($request, Closure $next, ...$roles)
{
if (in_array($request->user()->rol, $roles)) {
return $next($request);
} else {
return redirect()->action('SecurityController#noAutorizado');
}
}
And I'm triying to make a test for this middleware (phpUnit):
public function testUsuarioLogadoPuedeAccederAPantallaUsuarios()
{
$user = UsuariosTestFixtures::unAsignador();
$this->actingAs($user);
$request = Request::create('/usuarios', 'GET');
$middleware = new CheckRole();
$response = $middleware->handle($request,Closure $next,$user->getRole(), function () {});
$this->assertEquals($response, true);
}
But i'm retreiving this error: Argument 2 passed to App\Http\Middleware\CheckRole::handle() must be an instance of Closure, null given
I don't know how I have to pass the "Closure $next" on the $middleware->handle
I've tryed this:
public function testUsuarioLogadoPuedeAccederAPantallaUsuarios(Closure $next){...}
But It returns an error: Too few arguments to function UsuarioControllerTest::testUsuarioLogadoPuedeAccederAPantallaUsuarios(), 0 passed in C:\www\APPS\catsa\vendor\phpunit\phpunit\src\Framework\TestCase.php
What's the solution?
Thanks a lot!
A Closure in PHP is simply a function, so you need to pass a function as the second argument of your handle method.
In the context of Laravel middleware, the $next function represent the full pipeline of steps that the request goes through.
Obviously you can't (and don't need to) execute this pipeline during a test. What you need is just a function that return some values that your can test in an assertion.
What you can do is something like this:
//... setup code here
$middleware = new CheckRole();
$roles = ['role1', 'role2']; // change this with the desired roles
$result = $middleware->handle($request,function($request) {
return 'success';
},$roles);
$this->assertEquals('success', $result);
So, what is happening here?
If everything goes as planned (the user has the required role), the $next closure is executed and it returns success; on the other hand, if the user doesn't have the required role, the code takes the other path and it returns a RedirectResponse.
Finally, the assertion checks if success is returned, and it reports a failure if that doesn't happen.

Get authentication data inside of Constructor issue in Laravel5.3.19

I have upgrade Laravel from 4.2 to laravel5.3 but I can't access Authentication data inside of Constructor of Controller
I have as below Middleware but it never work for me
use App\Http\Controllers\BaseController;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Redirect;
use Auth;
use App\User;
class DashboardController extends BaseController
{
public $user;
public function __construct(Guard $guard, User $user)
{
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
return $next($request);
});
//$this->userID = Auth::user()?Auth::user()->id:null;
dd($user);// Result attributes: []
dd($guard);
dd($this->user);
}
}
The result after DD()
dd($guard);
DD($this->user);
NULL
It will return Null when I dd user property.
This is to be expected. The reason you have to assign the user inside the middleware closure is because the session middleware hasn't run yet. So, the closure you have above won't actually be called until later in the execution process.
If you move the dd($this->user) to inside the middleware closure or in to your one of you route methods in that controller it should be working absolutely fine.
Also, just FYI, in your middleware closure you can get the user instance from the request i.e. $request->user() will give you the authenticated user.
Hope this help!

Redirect user after login in laravel 5.1

I am trying to implement a feature where, after logging in, a user gets redirected to a URL depending on their role. I have the roles part set up, but I'm having trouble testing the user's properties immediately after login.
I followed the instructions here to create a user login page. I have an AuthController that looks like this:
namespace App\Http\Controllers\Auth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class AuthController extends Controller {
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
protected $redirectTo = '/test';
...
}
My __construct() function validates the user, but I don't know how to access the user object only immediately after login. This is what I presently have:
public function __construct() {
$this->middleware('guest', ['except' => 'getLogout']);
if ( \Auth::check() ) {
$user = \Auth::user();
if ( $user->admin() ) {
// an admin
$this->redirectTo = '/admin';
} else {
// it's a client
$this->redirectTo = '/client/dashboard';
}
}
$user = \Auth::user();
if ( is_object($user) ) {
} else {
$this->redirectTo = '/auth-not-object';
}
}
When I first attempt to log in with an administrator account, I get to the path /auth-not-object, because there isn't any authenticated user object at that point.
After having attempted to log in, but getting a bad redirect, when I revisit the /login url, I get redirected to /home, which I believe is the default $redirectTo in the traits this class uses. So that means we've passed the AuthController __construct() method without having changed the $redirectTo, even though there is an authenticated user.
I've found other questions, such as How to add extra logic on login condition in Laravel 5.2 and laravel redirect to url after login, but I don't understand how to apply those answers. For instance, the accepted answer to the second question shows new methods, getCredentials() and login(), which don't exist in the poster's original class. I am not sure in what class to add them, or where to call them from, in my codebase.
Other similar answers show a radically different way of authenticating users, such as this. It seems that, to use that solution, I would need to re-write my code, and forgo the use of the traits, which include bonus features like login throttling and so on.
Is there a way I can redirect users based on role after login, while still using these built-in traits?
Im not sure if the 5.1 auth is the same as the 5.2 auth, but if it is, remove all that from the construct and add this method:
protected function handleUserWasAuthenticated( Request $request, $throttles, $guard )
{
if ($throttles) {
$this->clearLoginAttempts( $request );
}
if ( method_exists( $this, 'authenticated' ) ) {
return $this->authenticated( $request, Auth::guard( $guard )->user() );
}
return redirect()->intended( $this->redirectTo );
}
this is the method that will determine the redirect and you have access to the user object.
EDIT
I take the above back, just add the following to your controller;
protected function authenticated( $request, $user ) {
return redirect()->intended( $user->admin() ? '/admin' : '/client/dashboard' );
}
That should work nicely

viaRemember not work - laravel

Auth :: attempt works perfect, but when you pass the second parameter "true" apparently does not care or does not recover with viaRemember
viaRemember fails to work, check this
controller User
`$`userdata = array(
'email' => trim(Input::get('username')),
'password' => trim(Input::get('password'))
);
if(Auth::attempt(`$`userdata, true)){
return Redirect::to('/dashboard');
}
view 'dashboard', always show 777
#if (Auth::viaRemember())
{{666}}
#else
{{777}}
#endif
I have hit the same obstacle, so looking into the code one can see that viaRemember is not meant to be used as a function to check if the user was logged into the system in one of all the ways a user can be logged in.
'viaRemember' is meant to check if a user was logged into the system specifically via the `viaRemember' cookie.
From what I gather, authentication of user is remembered in two ways:
a via remember cookie.
The cookie value is compared to the via remember field in the users table.
a session cookie.
The cookie value is used in the server to get the session from the
session store. On the session object from the store there is data attached. One of the
data items is the user id connected to the session. The first time
the session was created, the system attached the user id to the data
of the season.
In Illuminate\Auth\Guard class:
public function user()
{
if ($this->loggedOut) return;
// If we have already retrieved the user for the current request we can just
// return it back immediately. We do not want to pull the user data every
// request into the method because that would tremendously slow an app.
if ( ! is_null($this->user))
{
return $this->user;
}
$id = $this->session->get($this->getName());
// First we will try to load the user using the identifier in the session if
// one exists. Otherwise we will check for a "remember me" cookie in this
// request, and if one exists, attempt to retrieve the user using that.
$user = null;
if ( ! is_null($id))
{
$user = $this->provider->retrieveByID($id);
}
// If the user is null, but we decrypt a "recaller" cookie we can attempt to
// pull the user data on that cookie which serves as a remember cookie on
// the application. Once we have a user we can return it to the caller.
$recaller = $this->getRecaller();
if (is_null($user) && ! is_null($recaller))
{
$user = $this->getUserByRecaller($recaller);
}
return $this->user = $user;
}
The getUserByRecaller function is called only if the session cookie authentication did not work.
The viaRemember flag is only set in the getUserByRecaller function. The viaRemember method is only a simple getter method.
public function viaRemember()
{
return $this->viaRemember;
}
So in the end, we can use Auth::check() that does make all the checks including the viaRemember check. It calls the user() function in the Guard class.
It seems also the viaRemember is only an indicator. You need to do a type of Auth::check() the will get the process of authentication started and so the user() function will be called.
It seems that your project is on Laravel 4.0 but viaRemember() is added in Laravel 4.1! So that's expected.
in config\session.php file change the 'expire_on_close' = false to true and once you close restart your browser, it must be ok.

zfcUser getState in another module

how could i getState from zfcUser
in view/index.phtml i get it from $this->zfcUserIdentity()->getState();
but now i need to get this value ( state for this user who is logged in ), in other module /controller (this is my costum module controller)
so i need to get State from:
zfcUser/Entity/User
to
myModule/Controller
i watch this https://github.com/ZF-Commons/ZfcUser/wiki/How-to-check-if-the-user-is-logged-in but this solutons is not helpful
and this helps too, for me:
$sm = $this->getServiceLocator();
$auth = $sm->get('zfcuserauthservice');
if ($auth->hasIdentity()) {
$user_edit = $auth->getIdentity()->getPrem();
}
The state is a property from the user itself. So if you get the user throught the identification service, you can grab the state from there.
public function myFooAction()
{
if ($this->zfcUserAuthentication()->hasIdentity()) {
$user = $this->zfcUserAuthentication()->getIdentity();
$state = $user->getState();
}
}
Mind that when the user is not logged in, the if condition is false. Also the state can be null or any arbitrary value, so do not expect that every user returns a valid state (in other words, check the returned value!)
follow this code, I had same problem then I have manage how to use identity of logged in user via zfcUser
in other modules controller at topside,
use Zend\EventManager\EventManagerInterface;
then create this two function in the sameclass,
public function setEventManager(EventManagerInterface $events)
{
parent::setEventManager($events);
$controller = $this;
$events->attach('dispatch', function ($e) use ($controller) {
if (is_callable(array($controller, 'checkUserIdentity')))
{
call_user_func(array($controller, 'checkUserIdentity'));
}
}, 100);
}
public function checkUserIdentity()
{
if ($this->zfcUserAuthentication()->hasIdentity()) {
echo "<pre>"; print_r($this->zfcUserAuthentication()->getIdentity());die;
}
}
it will give this kind of output
Admin\Entity\User Object
(
[id:protected] => 2
[username:protected] =>
[email:protected] => rajat.modi#softwebsolutions.com
[displayName:protected] =>
[password:protected] => $2y$14$2WxYLE0DV0mH7txIRm7GkeVJB3mhD4FmnHmxmrkOXtUFL7S9PqWy6
[state:protected] =>
)
That's it you will automatically get Identity whether user is logged in if not then it will redirect to login page.
Hope this will helps