Laravel Authentication With Two Tables - laravel

I am trying to use Laravel's built-in Authentication class. Upon reading it, it seems that it only looks into one table as per the config/auth.php file. As per the doc, I can use syntax like this:
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// The user is active, not suspended, and exists.
}
My concern is, the email column is in my user table while password is in auth table. As I stated above, my understanding of Laravel's authentication is it only looks for one table only. Did I miss something?

Actually the solution is fantastically simple. You just need to override the getAuthPassword method which is defined in the Authenticatable trait, by adding this to your User model:
public function getAuthPassword()
{
return \DB::table('auth')->where('user_id', $this->id)->pluck('password');
}
And that's it, now the authentication system will get the password from the auth table before checking if it matches with user input.

You can authenticate user manually.
Retrieve user from your user table by email with his password from
auth table (via simple join or eloquent relations).
Validate that password is correct using \Hash::check($password, $hashedPassword); .
Login user manually usingAuth::login($user); if you are using Eloquent or Auth::loginUsingId($id); if simple DB query.
Docs:
Auth http://laravel.com/docs/5.1/authentication#other-authentication-methods
Hash http://laravel.com/docs/5.1/hashing

Related

Laravel 5.6 - Reset Password Tokens how to ensure they match?

When a user forgets their password and try to reset it, they get a reset password email link with a token:
site.com/my/password/reset/ddc3669ab1bbd78abe620ef910716ae91678bb4beb5cd8896e21efaaa0c9d5c6
On the backend though, the token in the database password_resets table looks like it's hashed:
$2y$10$O6pgU21FhsOcgpgeqR8RReFYoCGhHNBH5bHKxtE6q1tJMTUufrbr.
So when the route is visited, the only piece of identifying information passed is the token:
ddc3669ab1bbd78abe620ef910716ae91678bb4beb5cd8896e21efaaa0c9d5c6
// Controller Method
passwordResetVerifyByToken($token){
$record = DB::table('password_resets')->where('token', $token)
->first();
}
Ofcourse we won't get a record, as the plain token from the email will NOT match the hashed one in the database with the above query. So with the plain emailed token link, when the user clicks it, how can we compare it to the one in the database to verify it exists and is a matching token?
You should use the Hash::check method, which will return true or false depending of if the hash of the reset token matches the stored database value.
if (Hash::check($token, $row->token)) {
// The passwords match...
}
Laravel docs:
https://laravel.com/docs/5.6/hashing#basic-usage
Dont worry Laravel Have there own advanced function Hash you should try this
if (Hash::check($token, $row->token)) {
// write your code or other function
}

Make email authentication case insensitive in Laravel 5.7

I use the default email authentication in Laravel 5.7.3 (just updated from 5.4) with a sqlite DB. At login my email address gets validated case sensitive which is not what I want. It should be allowed to login with "JohnDoe#foobar.com" as well as "johndoe#foobar.com".
I've tried to add an accessor at my user model to always lowercase the database value.
public function getEmailAttribute($value) {
return strtolower($value);
}
But this one doesn't seem to be used by Auth at all. Additionally I don't know where to change the user input in the incomming request to lower case.
Is there a simple config case sensitive switch? Or where do I need to change/add scripts?
Thanks for your support
Daniel
Your accessor should be fine, but you should make sure that you also lowercase the given value, e.g. In your controller:
Assuming that you're using the default LoginController shipped from Laravel:
I overwrote the credentials method from AuthenticatesUsers in App\Http\Controllers\Auth\LoginController
protected function credentials(Request $request)
{
$credentials = [
$this->username() => strtolower($request->get($this->username())),
"password" => $request->get("password")
];
return $credentials;
}
This works fine, when all emails stored in the database are already stored all-lowercase. If you're starting from scratch you can enforce the emails to be stored lowercase by default. Just implement the following mutator in your App\User:
public function setEmailAttribute($value)
{
$this->attributes['email'] = strtolower($value);
}
If you have stored mixed-case email already, you can update all emails to lowercase emails using this query:
UPDATE users SET email = LOWER(email);
But this still feels kind of incomplete and you maybe don't want to manipulate your data this way. I am pretty much sure that there are more possibilities to make this happen but unfortunately I am not able to dig into this further for now. However my next attempt would be to extend/write a custom UserProvider.
You have to call getEmailAttribute(/your email here/)
before login and signup like this
$request->email = getEmailAttribute($request->get('email'));

laravel login with remember me feature without field in the database

I'm developing a website using Laravel with an existing database.
My User table doesn't have a remember me field. But I want users always login with remember me feature. Can anyone help?
"Remember me" functionality NEEDS a field in DB. Actually you have to store the "remember me" cookie somewhere in your program. Where is a better place than DB to do this??
First you have to add remember_token (100-character string) to your Users table in database which will be used to store the "remember me" token.
In the next step, On your login attemp you must add $remember parameter like this:
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
// The user is being remembered...
}
after this code, your user will be remembered by his remember cookie. SO he can be remembered like this:
if (Auth::viaRemember()) {
//
}
Anyway, if you want to store the remember_token in another table, you have define a model like RememberToken and add this relationship to your Users model:
public function rememberToken() {
return $this->hasOne('RememberToken'); // also add foreign keys
}
And now some overriding is needed!. First override getRememberToken() and setRememberToken() methods and also you need to override getRememberTokenName().
As a result EloquentUserProvider::retrieveByToken() should be changed in EloquentUserProvider class. You probably have to make your User model to join remember_tokens table on every query by adding global scope to it, and return 'remember_tokens.token' from getRememberTokenName() method.
Is it really necessary by the way?

Password verify always returns fail in Laravel (Hash::check)

I've got an issue when I try to validate the post password via Hash::check in Laravel 5.5
I made a posts table (in this case sales table) with password column. When I try to create the post, it's working perfectly and the password is hashed and also belongs to logged in User. Then on the current post page is a button with an input (password) to delete that specific post, but the condition is always false.
My Controller public function destroy(Request $request, $id)
$input_pass = request('input_password');
$sale = Sale::find($id);
$hashed = $sale->password;
// Check if sale password is correct
if (Hash::check($input_pass, $sale->password)) {
$sale->delete();
} else {
// something else to do
}
For the post store, I used bcrypt method to hash the password. I've been also trying to dd('sale->password') which refers to column in sales table (correct) and dd('$input_pass') which refers to typed in password in DELETE form (also correct) - so I'm a little bit confused, why the pass don't match.
From your comment I find that you have a logical error where you initially hash your password and persist it in DB.
You are passing the string password to bcrypt where it should actually be something like request('password')
Change
'password' => bcrypt('password'),
to
'password' => bcrypt(request('password')),

Laravel How to store extra data/value in session Laravel

I'm using default auth() in laravel login (email & password)
Now i try to take input from the user in text field like (Age or City)
Now i want to store (Age/City) in my session.
Help me
You can use session() helper:
session('age', 18); // saves age into session
$age = session('age')`; // gets age from session
Update
If you want to save Age and City after user registration, you should store this data in a DB, not in a session. You can add some fileds in create method of app\Http\Controllers\Auth\AuthController.php
You can use
Session::put('key', 'value');
To get key from Session use
Session::get('key');
You can use the session() helper function as #Alexey Mezenin answer.
Laravel Session Documentation
Ok let me enlighten you. if you want to store it in session do it this way.
session('country', $user->country); // save
$country = session('country')`; // retrieve
But that is not the way we do in Laravel like frameworks, it uses models
once the user is authenticated each time when we refresh the page, application looks for the database users table whether the user exists in the table. the authenticated user model is a user model too. so through it we can extract any column. first thing is add extra fields to the User class(Model) $fillable array.
so it would look something like this.
User.php
protected $fillable = ['username', 'password', 'remember_token', 'country'];
so after simply logging in with user name and password in anywhere just use Request class or Auth facade. Facades are not too recommended so here for your good as a new one i would just say how to use Request. Suppose you want to retrieve your Authenticated user country inside TestController.php here is how it could be used in the methods.
TestController.php
use Illuminate\Http\Request;
public function testMethod(Request $request)
{
$someCountry = $request->user()->country; //gets the logged in user country
dd($someCountry); //dd is die and dump, could be used for debugging purposes like var_dump() method
}
Using Request
public function ControllerName (Request $request){
$request->session()->put('session_age', $age);
}
Get session_age
$get_session_age = $request->session()->get('session_age');
Using Session
public function ControllerName (){
Session::put('age',$age);
}
Get the session
$session_age = Session::get('age');
Don't forget to define Session or Request in your controller!!!
use App\Http\Requests;
use Session;
To work with session in your controller you need to include session first in your controller
use Session;
After that for store data in session. There is several ways to do it. I prefer this one (in controller)
session()->put('key',$value);
To display session data in your View you can do it like this
#if(Session::has('key'))
I'v got session data
#else
I don't have session data
#endif
To get session data in your Controller you can do it like this
session()->get('key')
//or
session()->get('key','defaul_value_if_session_dont_exist')
When you are done with your data in session you can delete it like this (in controller)
session()->forget('key');
All this basic usage of session is well documented in official Laravel documentation here.
Hope it helps you

Resources