Call authenticate manually in router middleware - php

I created a CustomAuth middleware to use in routes to authenticate by "user_id" in request body or "Authentication" in request header.
I need call Authenticate class case "user_id" isn't passed.
class CustomAuth
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $guards)
{
if ($request->get('user_id')) {
Auth::loginUsingId($request->get('user_id'));
} else {
<-- here -->
}
return $next($request);
}
}
Obs: I use whitelist ip middleware as well.

Do you want to authenticate user in login form by user_id?
if yes you should change login form and make change in this file:
vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php
public function username()
{
return 'email'; // default is email but you can change it to id or user_id if you have this column in your users table
}

Related

Laravel cannot pass multiple middleware

recently i created two middlewares which is one for user called device, and one other for super user which is high level of admin. This is my middleware
Role Device Middleware
<?php
namespace App\Http\Middleware;
use Closure;
class RoleDevice
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::check() && Auth::User()->role=='device'){
return $next($request);
}
return redirect()->route('login')->with('danger',"You don't have an access");
}
}
Role Device Super User
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
use User;
class RoleSuper
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::check() && Auth::User()->role=='super'){
return $next($request);
}
return redirect()->route('login')->with('danger',"You don't have an access");
}
}
after i created the middlewares, i put into the routes which is one route could access two middlewares. Here is one of my route.
Route::get('/dashboard','DashboardController#index')->middleware(['rolesuper','roledevice'])->name('dashboard');
and when i try to log in into my website, it returns
You don't have an access
which is don't pass into the middleware.
i hope i get any comments above !
thanks.
Middlewares are executed in the order the are passed. So in case first middleware returns redirect response that's it - second middleware won't be executed.
You could combine both middleware into one and pass available roles as middleware parameter or just create single middleware for this that will verify if user is authorized.

Laravel 5.2 Authentication Token

I'm trying to implement a Token based authentication in Laravel 5.2. What I've done is:
Routes.php
Route::group([
'middleware' => ['auth:api']
], function() {
Route::get('/api/reservation', 'apiController#get');
});
I've modified the User model and added the api_token field and added a new user with a random string via seeders:
Migration
Schema::table('users', function (Blueprint $table) {
$table->string('api_token', 60)->unique()->nullable()->default(null);
});
Seeder
User::create([
...,
'api_token' => str_random(60),
]);
Controller
class apiController extends Controller
{
function get(Request $request) {
return Reserva::all();
}
}
Then, In Postman I try to GET the url adding /api/reservation?api_token=xxxxx with the token I have in the database but I always get Unauthorized. Something weird is if I do a dd($this->auth) on the authentication middleware I get a TokenGuard object with the name='web'. Isn't It supposed to be api?
Maybe I'm misunderstanding something, can you guys give me a hint? Thank you
The auth:api middleware you are using uses Laravel Passport. You cannot use it if you want a custom token based authentication like you do where you create your own tokens.
If you want to use Passport, do this:
Keep your routes like that. The routes that require authentication must be inside of the auth:api middleware.
You can remove the api_token field of your users table. The $table->rememberToken() function in the migration is completely different than the API token you think of. In fact, tokens are not stored in the database at all. The token you see in the oauth_access_token table in the database is not the token you use for you HTTP requests.
Do NOT create a custom token like you do. Check that the login/password couple of the user is valid, generate a token and return it to the consumer of the API like that:
if (Auth::attempt(['login' => $req->login, 'password' => $req->password])) {
$user = Auth::user();
$token = $user->createToken('ToutelaBreizh')->accessToken;
return response()->json(['token' => $token],200);
}
Beware to place the login/register routes OUTSIDE of the auth:api middleware, otherwise you would need to give a token to a route that is supposed to give you this token - it makes no sense.
Next, make sure you send the token to the API in the Authorization header of the request, and not in the request parameters like you do. Add in Postman the following header:
Authorization: Bearer your_token_retrieved_before
Now you're pretty much done, you can use your API with Postman.
In case someone else face this problem. My problem was In the Authenticate middleware. I had an old version somehow.
I had this Authenticate middleware:
class Authenticate
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
return $next($request);
}
}
And I solved it by changing it with this:
class Authenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return rediresct()->guest('login');
}
}
return $next($request);
}
}

Laravel looses Session ( Authentication)

I have a problem with a specific route on Laravel. Every second time (and sometimes on the first time) when ill call a specific route, ill get an 401 error, returned from the Authentication Middleware.
File Middleware/Authenticate.php
class Authenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401); // THIS IS CALLED
} else {
return redirect()->guest('login');
}
}
return $next($request);
}
From that route:
Route::group(['middleware' => 'auth'], function () {
.........
Route::get('events', 'TaskController#events');
});
TaskController.php
public function events(Request $request) {
$time_from = $request->start;
$time_to = $request->end;
$events = array();
$user_id = Auth::user()->id;
.....
return response()->json($events, 200);
}
All called from a JQuery $.get Request. I dont know why Laravel thinks i am a guest, and then looses the Session?
When you are doing ajax/api requests laravel thinks you're guest because session based authentications doesn't apply to this type of calls. Whenever you use auth middleware you'll get 401 on ajax, even if you're authenticated.
You need some type of token based authentication for the ajax/api calls, that sends Authentications header on requests and new middleware that handles authentications for it.

Multiple dynamic url redirect in Laravel

I have looked at many similar questions bu they don't approach the real problem. I would like to redirect a user to a certain url just after login depending on a condition about the user.
I know this can be archieved with a middleware so I have tried this in app\Http\Middleware\RedirectIfAuthenticated.php
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::User()->check()) {
$redirect = '/client';
if (Auth::user()->hasRole('admin')){
$redirect = '/admin';
}
return redirect($redirect);
}
return $next($request);
}
}
I realise now this will not work just after login. I'd like to redirect a user depending whether he/she is an admin or a client. I know I could use: protected $redirectPath = '/url/to/redirect'; but I have multiple pages to redirect to.
What is the best way to do this?
You could over-write the redirect method offered up by the trait in app/Http/Controllers/Auth/AuthController.php
public function redirectPath()
{
if (Auth::user()->hasRole('admin')){
return '/admin';
}
return '/client';
}
Put that in your AuthController.php.

How can I use laravel 5.1 middleware parameter for multiple auth and protected routes?

I'm new to laravel 5.1.
How can I use middleware parameter to protect my admin routes from users ?
something like this:
Route::group(['middleware' => 'auth:admin'], function()
/* Admin only Routes*/
{
//////
});
I have a field "role" in my "users" table that get two values:
1 for admin
2 for users
In my application, users, have their protected route.
I don't want to use packages.
You can do something like this. Inject the Guard class, then use it to check the user. You dont need to pass the parameter really. Just name your middleware 'admin' or something. The following middleware will check if the current user's role is admin, and if not, redirect to another route. You can do whatever you prefer on failure.
<?php
namespace Portal\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Admin
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if($this->auth->user()->role != 'admin') {
return redirect()->route('not-an-admin');
}
return $next($request);
}
}
In case you do want to pass the parameter, you can do this:
public function handle($request, Closure $next, $role)
{
if($this->auth->user()->role != $role) {
return redirect()->route('roles-dont-match');
}
return $next($request);
}

Categories