Laravel - user login - laravel

I use Laravel 5.4 and need to login user in my system. I have next login.blade.php
where i have email and password field. In my controller I have next
protected function log() {
$email=Input::get('email');
$pass=Input::get('password');
$user = DB::select("SELECT * FROM users where email = '".$email."' and password = '".$pass."'");
foreach($user as $users){
if(Input::get('email') == $users->email){
return redirect('/');
}else{
return view('site.warning');
}
}
}
How can I return logged user in my redirect('/') and show them in my site.
Any idea?

Use the attempt() method:
if (Auth::attempt(['email' => $request->email, 'password' => $request->password])) {
From the docs:
The attempt method accepts an array of key / value pairs as its first argument. The values in the array will be used to find the user in your database table. So, in the example above, the user will be retrieved by the value of the email column. If the user is found, the hashed password stored in the database will be compared with the password value passed to the method via the array.
This method will work for you if you're using bcrypt() or Hash::make() to generate password hash.

Please do not create your own login system!
Now that's out of the way the explanation.
There is (almost) no good reason to create your own login system, as your code already showed. Your current code is very VERY insecure due to storing passwords in plain text. Please read up on resent security advice.
The even better option is using Laravels build-in auth.
https://laravel.com/docs/5.4/authentication
If you do try to use this build-in authentication methods you will be able to get the current authenticated user by using Auth::user() this can be used in your blade files as well as in your controllers.

You cannot (maybe you can) but you certainly should't store user's password unhashed. Laravel has build artisan command: php artisan make:auth. You may use it, and retrieve him in the show method for example (thro the URL, passing id). Or just retrieve him via Auth::user(). Planty of choices.

Related

Login stops working after changing the input field name "email" to "login-email"

I am developing a Laravel 6.6.2 project and I came across this problem I can't seem to fix.
In the file login.blade.php view i'm trying to change name="email" in the input fields to name="login-email". But when I do this the login doesn't work anymore. So I think that Laravel uses the name email somewhere to validate the login. I can't find where Laravel looks for the name email instead of login-email and if this even is needed to change?
The reason I need to change this is because javascripts use the name value too. (Because I brought a template). I am still learning Laravel so don't be to harsh. Thanks in Advance.
Laravel has excellent documentation. This is always a good place to start.
# Authenticating
https://laravel.com/docs/6.x/authentication#included-authenticating
Username Customization
By default, Laravel uses the email field for authentication. If you would like to customize this, you may define a username method on your LoginController:
In your case, you would return login-email from the username method.
public function username()
{
return 'login-email';
}
Of course, you will also need to add or rename this field in the database if you haven't already.
Alternatively to renaming the field in the database, you could override the credentials method.
protected function credentials(Request $request)
{
return [
'email' => $request->{$this->username()},
'password' => $request->password,
];
}

Laravel 5.8 - save user emails encrypted

I'm looking for a way to encrypt the user emails in the database. Since Encrypt always generates a different string, it fails.
So I took sha1.
in AuthenticatesUsers I've changed the credentials method to:
protected function credentials(Request $request)
{
return ['email' => sha1(strtolower($request->email)), 'password' => ($request->password)];
}
This works great for the login/registration. But there are problems with resetting the password.
Resetting the password uses the SendsPasswordResetEmails trait.
There it this credentials method:
protected function credentials(Request $request)
{
return $request->only('email');
}
This always fails, cause it does not find the user (cause the user is saved with sha1 email)
if I change it to return ['email' => sha1(strtolower($request['email']))];
I get the error, that the email is not in the right RFC standart, to send a email. The Problem is, I don't really find the place, where laravel is searchig for the user with this email. Anyway, I don't really have a clue, how I can solve this problem at all.
I want to encrypt the email itself, because in germany there is a law which forces us to store personal data encrypted, like the email.
First thing to say is that Hashing is not the same as Encryption.
Encryption is a two way function, that is if you can encrypt an email you can decrypt it with a reverse function, if you know the encryption key, and obtain the original email.
Hashing is a one way function, that is if you hash a password you can't obtain the original password with a reverse function, you can only verify that, when you input the password again, the hash you obtain matches the original hash, so you only know that the two password are identical.
You usually store password hashed, not crypted, so even the administrator can't recover the original password, he con only verify that a input from a user has a hash that match the original password he entered.
You can read more in this stackoverflow question: Difference between Hashing a Password and Encrypting it.
The sha1() is a hashing function, so is not reversable, you can't obtain the original email.
Laravel has the functions encrypt() and decrypt() to encrypt things, see the docs on encryption, and has the functions Hash::make() to hash a password and Hash::check() to verify the password, see the docs on hashing.
So if you want to encrypt the emails, not hashing them with sha1, you should use encrypt() and decrypt().
The best way for you is to use mutators, i.e.:
public function getEmailAttribute($value)
{
return decrypt($value);
}
public function setEmailAttribute($value)
{
$this->attributes['email'] = encrypt($value);
}
So you will have email encrypted in the database and you can use $user->email in your code.
But I have to warn you that with encrypted email the login process is irreparably broken, you have to use another unique field like username for the login, not the email, so in your login controller you have to write:
public function username()
{
return 'username';
}

Laravel password reset token is different when it is saved in database

I am developing a Laravel application. I am now customising the password reset feature. There is an issue with retrieving the password reset token back from the database because the token string is changed when it is saved in the database from when it is generated.
I explicitly generate the password reset token like this
$token = app('auth.password.broker')->createToken($user)
Then, I tried to retrieve the password reset by using that token like this.
$password_reset = DB::table('password_resets')
->where('token', request('token'))
->first();
I cannot retrieve it. It always return null. Because the token value is different from when it was generated as in the screenshots below.
Why is that happening and how can I fix it?
The token gets hashed before it's stored in the database. It gets hashed in the DatabaseTokenRepository on line 110: 'token' => $this->hasher->make($token).
You won't be able to query by token. You would only be able to check a plain token value against a hashed value with the check method in the HashManager class, for example.
Base on Passport
your code should be something like this
$token = app('auth.password.broker')->createToken($user)->accessToken

Laravel middleware is "bypassed" when i submit the invalid token, but when it is a valid token, the middleware is executed

all my fellow friends, i have a question.
Route::group([
'middleware' => ['ensure.role:store', 'auth:api']
]
For simplification,
i have two roles : ADMIN and STORE
I have created a middleware that will validate user role, and if the user role is correct, then will allow the user to access the route.
It works fine.
I tried using ADMIN Jwt Token to access STORE routes, and rightfully i am kicked out, and vice versa.
But now, if i modify the token, lets say i add a string to any part of the token, and try to access any route, actually i am allowed to.
I tried var_dump and print something on the related middleware, and here are my observation.
1. If the token is VALID as one of the user role, then
the var_dump is executed, (means the middleware is executed)
2. if the token is INVALID as in i add / modify the original
token, then the var_dump is not executed, and so are the
others route middleware.
I am wondering what causes this behavior, and what could be the fix for this issue, as i need to throw 401 unauthenticated in any token invalid case.
Thank you
I figured it out.
After series of testing and reading, i found out that after laravel 5.3 and above, constructor is called before middleware. And because in my constructor i am using an user object before i am authenticated by the middleware, i encountered constructor error, because user is null.
Of course it is a bad practice to use user object in the construct, however due to the convenience of usage, i still decided to use it.
It sounds complex to use closure based middleware as alternative solution
So i use a workaround to do it.
I create a helper function that return me true if there is an user object or return abort(401); if there is no user object, then add this one line to all the constructors.
$this->checkAccess = EnsureRoleUtil::check('admin');
After that, i just do my next constructor as normally
public function __construct() {
$this->checkAccess = EnsureRoleUtil::check('admin');
$this->user = Auth::user();
$this->categoryM = new CategoryManager($this->user);
}
However, to be noted, it is not a good practice, it is just a hack / workaround.

How to get data from JWT if didn't have users table in laravel?

I try to implement microservice arhitecture.Because I new in it,can maybe someone can tell me:
- can I use JWT for communication to services,when someone login into one service.Is that secure way or there is something better?
- how do I parse JWT and get user id or some other data from it to have it in other service which didn't have users table?Like is it expiried,user id...
Thank you a loot if someone can help me to send me a direction for it.
I'm partial to the tymon/jwt-auth package for this, which largely uses 'namshi/jose' under the hood. As long as the jwt.secret is the same between each system that may need to use the tokens, you should be able to just call JWTAuth::getPayload($token)->toArray() to decode them.
You do need a user table, but it doesn't have to be the user table already speced out in Laravel. Any Model that implements the Illuminate\Auth\Authenticatable interface, such as by extending the Illuminate\Foundation\Auth\User model will do.
If you want to inject additional data into the token beyond the user table that the login credentials are being validated against, just add an array as the second parameter to the login attempt:
//The key names here are defined by the return values of methods described in the Authenticatable interface.
$credentials = [
'username' => 'your_user',
'password' => 'your_password'
];
$customClaims = [
'someOtherDatapoint' => 'more_data'
];
$token = JWTAuth::attempt($credentials, $customClaims);
You could also go directly to the token-creation without authentication:
$user = app(YourUserModel::class)->first($id);
$token = JWTAuth::fromUser($user, $customClaims);
This is relatively secure, but I'm not sure if it's the best way to communicate encrypted data. You might want to just use the encrypt() and decrypt() helper functions, that are based off the APP_KEY. You could also look at Laravel-Passport, https://laravel.com/docs/5.6/passport, for authentication, which uses OAuth2.

Resources