Laravel 5.1 auth system with status - php

I am new to laravel I have integrated inbuilt authentication system and works perfect. Now I also want to consider status field of user table while authenticate. I search a lot but could not find proper way to integrate such functionality with inbuilt laravel's authentication system.

Considering user status when authenticating is simple. There are 2 ways to do that, depending whether you call Auth::attempt() manually or you use AuthenticatesUsers or RegistersAndAuthenticatesUsers trait in your controller.
If you are calling Auth::attempt() manually, you always pass an array of credentials to the method. Those credentials are used to fetch user from the database. Add status field to those credentials and only users with given status will be able to log in, e.g.:
Auth::attempt([
'username' => Request::input('username'),
'password' => Request::input('password'),
'status' => 'active'
]);
Above will allow only users with status=active to log in.
If you are using AuthenticatesUsers or RegistersAndAuthenticatesUsers trait in your controller, you need to override the getCredentials() method. This method should return the same array that you'd pass to Auth::attempt():
protected function getCredentials(Request $request) {
return [
'username' => Request::input('username'),
'password' => Request::input('password'),
'status' => 'active'
];
}

Related

Laravel AUTH() - Adding additional users (without registration)

I've tried to find information on this and can't find any. I have a Laravel 7 application and have used the Laravel AUTH scaffolding for login/registration/authentication.
I would like to allow a logged in user to add other users, I've done the simply but pushing the data in to the database (obviously no password is set) but now I would like to send an email to these users asking them to set a password and am unsure how to do this. I see Laravel has some events related to auth built in such as this called in the register function of RegistersUsers.php:
event(new Registered($user = $this->create($request->all())));
Can anyone confirm where I would need to create such an event and how I call it from the store function that adds the user to the database?
Any help much appreciated.
As suggested by #lagbox I simply did the following:
$user = \App\User::create([
'firstname' => $validatedData['firstname'],
'lastname' => $validatedData['lastname'],
'email' => $validatedData['email'],
'company_id' => $company_id,
'phone_number' => $validatedData['phone_number'],
'password' => Str::random(16),
]);
event(new Registered($user));

Set Default Guard After Register/Login When Using Multiple Guards in Laravel

I am working on a Laravel API project where the user's table has a column of type with a value of either student or company.
For the purpose of authenticating the users of both types and restricting access to certain routes, I have set up two guards with the same driver (JWT) and provider (Users).
'company' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => false,
],
'student' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => false,
],
In the login and register method of my controller, I am accessing the value of user type from the form where the user selects his role (student or company).
public function register(){
$user= $this->create(request()->all());
$token=auth(request('type'))->login($user);
return $this->respondWithToken($token);
}
The purpose to access the user type is to pass that value to the auth() method which in turn uses it to log in the user through that specific guard.
The issue is: I have to use that request(type) in every controller method wherever authentication is necessary and there is need to use use the auth() related methods. e.g jwt respondwithtoken() method
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth(request('type'))->factory()->getTTL() * 60
]);
}
What I want: I want a mechanism to set the guard dynamically after the user has successfully logged in and I should able be to use the auth() method without passing any argument to it.
// shoulduseguarddynamically(request('type'));
P.S: Please also verify that using guards in this way when I have single table with multi-type users is the right approach?
First off, your approach is not really safe - just tampering with the 'type' will grant you access to places you are not supposed to go.
You would be better using Gates instead of guards for this,
You can check them in the docs here: https://laravel.com/docs/7.x/authorization#gates

Laravel customise logic for login/password reset

I need to customise the logic for Laravel's authentication. I found a solution on SO, by overriding the credentials method in the LoginController like so:
return ['email' => $request->{$this->username()}, 'password' => $request->password, 'status_id' => $whatever];
But now I discovered an issue where a user can still reset their password and then they get signed in automatically. So how can I disable password resets for users who should not be allowed to sign in?
There is a method on the ResetsPasswords trait called resetPassword()
Override this in your Auth/ResetPasswordController and replace the line
$this->guard()->login($user);
with whatever functionality you want to achieve after the password reset.
If you want to prevent a disabled user from resetting their password, use a middleware to check if the account is disabled before continuing with the password reset.
You can create a new column to your user table isbanned that excepts only boolean value. And check further of this column value of a user that requests for reset password. If the value is TRUE, don't give the reset link, otherwise, give it.
Below you can see this example:
if (Auth::attempt(array('phone' => $request->input('phone'), 'password' => $request->input('password'), 'isactive' => '1', 'isbannes' => '0'), $remember)){
// your logic
}
Hope this helps you.

Change the Laravel Login System in Laravel 5.5

I'm trying to determine if the user is allowed to login. Addiotional to the email with the correct password, I want to check if the user is active or not.
There is a active column in my database with the values "n" and "y". The login is supposed to fail if active == "n".
Now I'm trying to add this to the Login Controller but where ever I'm trying to put this if/else condition, it just gets ignored.
In the Laravel Doc. I found this:
Specifying Additional Conditions:
If you wish, you may also add extra conditions to the authentication query in addition to the user's e-mail and password. For example, we may verify that user is marked as "active":
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1 ( in my case "y"])) {
// The user is active, not suspended, and exists.
}
But this haven't workd for me.. Thats why I want to ask where do I have to put this code ( I've tried in the authenticatesUsers.php #login function ) and if I have to modify the code in a specific way? Laravel 5.5 is handling the login system a little bit different then 5.4 ( thats what I think at least )
Thanks for any help!
Your best way to do this is to add a method login to your LoginController
public function login(Request $request)
{
if (Auth::attempt(['email' => $request->email, 'password' => $request->password, 'active' => 'y'])) {
return redirect()->intended('dashboard');
} else{
return redirect('/');
}
}
Remember to add use Illuminate\Support\Facades\Auth; and use Illuminate\Http\Request; to the top of your controller.
Tested with 0 and 1, and with n and y and it worked as expected
You need to create a method named 'attemptLogin' in your LoginController and add that code to the method as follows
/**
* Attempt to log the user into the application.
*
* #param \Illuminate\Http\Request $request
* #return bool
*/
protected function attemptLogin(Request $request)
{
return Auth::attempt(['email' => $request->email, 'password' => $request->password, 'active' => '1'], $request->filled('remember')
);
}
This will override the method in the authenticatesusers trait while still utilising all the built in features of laravel authentication.
You must not forget to add this at the top of the page among your use directives
use Illuminate\Support\Facades\Auth;
Then you are good to go.
Hope it helps someone

How to limit user actions with Laravel Passport Scopes + Password Grant Type

I have set up the Laravel Passport package for Laravel 5.3 just as described in the official documentation (https://laravel.com/docs/5.3/passport#introduction).
I want the API to be consumed by a mobile application, so I am trying to implement Password Grant Tokens. I have created a password grant client, and the token request process...
$response = $http->post('http://my-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'username' => 'my#email.com',
'password' => 'my-password',
'scope' => '',
],
]);
...Just works as expected, returning an access-token and a refresh-token for one of my users.
But now I want to define some scopes so I can limit the access of users... Following the documentation again, I have them defined in boot method of AuthServiceProvider.php like:
Passport::tokensCan([
'admin' => 'Perform every action',
'user' => 'Perform only normal user actions',
]);
In this scenario, if a "malicious" normal user requested a token (using the above POST call) specifying 'scope' => 'admin', he or she would get an 'admin' token... and that is not what I want.
Thus, I would like to know how is the workflow in this situation to effectively limit the access to normal users, and where do I have to implement the scope validation logic.
Thanks in advance.
One way to go about this would be to create a middleware
For example if you only want users with an email from example.com to request the admin domain you can do something like this
Example ScopeLogic.php middleware:
if ($request->input('grant_type') === 'password') {
$scope = $request->input('scope');
$username = $request->input('username');
if ($scope === 'admin' && (strpos($username, '#example.com') === false)) {
return response()->json(['message' => "Not authorized to request admin scope"], 401);
}
}
return $next($request);
Of course, you would have to add this scope to your $routeMiddleware array in Kernel.php
protected $routeMiddleware = [
...
'check-scopes' => \App\Http\Middleware\ScopeLogic::class
]
As well as wrap Passport::routes() in AuthServiceProvider.php to check for this middleware
\Route::group(['middleware' => 'check-scopes'], function() {
Passport::routes();
});
Passport will also check that a correct username and passport combination was passed so you don't have to worry about that in the middleware
In my opinion, I think what confuses most people with OAuth and APIs is that scopes are tied to "clients" and not the "resource owner" themselves. Clients should be able to talk to an API using an admin scope or no scopes at all if needed. If they use an admin-ish type scope together with user context (password grant, authorization code grant, etc), then there is no stopping them from making calls that require such a scope against that user in the API. To me, the only person that can truly be classified as malicious would be one who manages to steal an access token containing an admin scope. That is why API implementors are allowed to specify what scopes to grant a client and if it's a first party app that uses something like the Password Grant, then you as a user has no choice but to trust it with your data.
I don't know how one would do this and use the retrieved token inside another's mobile app but if you did try requesting a token manually yourself with an admin scope, then I really don't see anything wrong that (other than you giving the app more control with you set as user context, so it may even be counter productive?)
If you need more control than that, then you need to go past your API and create something like application-level permissions for each user inside your resource server.
I forget where I read it, some Github issues somewhere, but apparently Laravel doesn't have that ability built in, each client is the treated the same equally, out of the box.
A user provided a good solution, and I built upon it here: https://stackoverflow.com/a/55285483/1132557

Categories