I am making a custom login in Laravel 7. Register is done correctly but login is not working properly. What can i do for login using custom table user_master.
My database table is user_masters.
User_master model:
<?php
namespace App;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User_master extends Model implements Authenticatable
{
//
use HasApiTokens, Notifiable;
protected $fillable = [
'user_full_name', 'user_email', 'user_password','user_otp_code','user_phone'
];
protected $hidden = [
'user_password'
];
protected $casts = [
'email_verified_at' => 'datetime',
];
}
This my controller. what have I done wrong here?
<?php
// namespace App\Http\Controllers;
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\User_master;
use Illuminate\Support\Facades\Auth;
use Validator;
use Illuminate\Http\Request;
class UserMasterController extends Controller
{
//
public $successStatus = 200;
/**
* login api
*
* #return \Illuminate\Http\Response
*/
public function login(){
if(Auth::attempt(['user_full_name' => request('user_full_name')])){
$user = Auth::user_master();
$success['token'] = $user->createToken('MyApp')-> accessToken;
return response()->json(['success' => $success], $this-> successStatus);
}
else{
return response()->json(['error'=>'Unauthorised'], 401);
}
}
/**
* Register api
*
* #return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'user_full_name' => 'required',
'user_email' => 'required|email',
'user_password' => 'required',
'c_password' => 'required|same:user_password',
]);
if ($validator->fails()) {
return response()->json(['error'=>$validator->errors()], 401);
}
$input = $request->all();
$input['user_password'] = bcrypt($input['user_password']);
$user = user_master::create($input);
$success['token'] = $user->createToken('MyApp')-> accessToken;
$success['user_full_name'] = $user->user_full_name;
return response()->json(['success'=>$success], $this-> successStatus);
}
}
You need to set your authentication driver properly to work with your custom user Model.
Make these configuration in config/auth.php file ,in providers section:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User_master::class, // <---- Your custom user model
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
Notice:
You must implement Illuminate\Contracts\Auth\Authenticatable interface.
Illuminate\Foundation\Auth\User is a class, you cannot implement it.
Related
I am making an authentication api using Laravel passport
when I try to return the access token I get this :
"access_token": {
"name": "authToken",
"abilities": [
"*"
],
"tokenable_id": 60,
"tokenable_type": "App\\Models\\User",
"updated_at": "2022-06-03T17:07:16.000000Z",
"created_at": "2022-06-03T17:07:16.000000Z",
"id": 12
}
},
"message": "data has been retrieved"
}
I don't know where the token is
and this is my login controller
$rules =[
'email' => 'email|required',
'password' => 'required'
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json(['message' => 'there is been an error', 'error message' => $validator->errors()]);
}
$loginData = $request->input();
if (!auth()->attempt($loginData)) {
return response(['message' => 'Invalid credentials']);
}
$user = $request->user();
$data['user'] = $user;
$data['access_token'] = $user->createToken('authToken')->accessToken;
return response()->json([$data, "message" => "data has been retrieved"]) ;
I think you have implemented all the necessary commands to work with laravel passport.
This makes it possible to take with a refresh token.
Try this:
use Laravel\Passport\Client as OClient;
use GuzzleHttp\Client;
public function login(Request $request){
....
// $laravelPasswordGrantClientId - this is the id of the client whose database you have
$oClient = OClient::find($laravelPasswordGrantClientId);
return response()->json($this->getTokenAndRefreshToken($oClient, request('email'), request('password')),200);
}
public function getTokenAndRefreshToken(OClient $oClient, $email, $password) {
$oClient = OClient::find($laravelPasswordGrantClientId);
$http = new Client;
$response = $http->request('POST', 'http://your.domain.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => $oClient->id,
'client_secret' => $oClient->secret,
'username' => $email,
'password' => $password,
'scope' => '*',
],
]);
$result = json_decode((string) $response->getBody(), true);
return $result;
}
app/Models/User.php
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
//use Laravel\Sanctum\HasApiTokens;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
make sure you have Laravel\Passport\HasApiTokens; in User.php
So I have 2 tables one is the User table and the other is the related UserProfile table. I wanted to fill them with dummy data but I cant get it to work that when I run the seeder it will fill both tables. For now it will fill the User table with dummy data only.
Solution found(any sugestions are welcome)
User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use App\Models\UserProfile;
class User extends Authenticatable implements MustVerifyEmail
{
use HasFactory, Notifiable, HasApiTokens;
protected $table = 'user';
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
public function profile()
{
return $this->hasOne(UserProfile::class, 'user_id');
}
}
UserProfile.php
namespace App\Models;
use App\Models\User;
class UserProfile
{
protected $table = 'user_profile';
protected $fillable = [
'user_id',
'firstname',
'lastname',
];
public function user()
{
return $this->belongsTo(User::class, 'id');
}
}
UserFactory.php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
protected $model = User::class;
public function definition()
{
return [
'name' => $this->faker->firstName,
'email' => $this->faker->unique()->safeEmail,
'active' => mt_rand(0,1),
'role' => mt_rand(0,5),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
'remember_token' => Str::random(10),
];
}
}
UserProfileFactory.php
namespace Database\Factories;
use App\Models\UserProfile;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserProfileFactory extends Factory
{
protected $model = UserProfile::class;
public function definition()
{
return [
'user_id' => User::Factory(),
'firstname' => $this->faker->firstName,
'lastname' => $this->faker->lastName,
'default_language' => 'en',
];
}
}
DatabaseSeeder.php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
//solution
User::factory(100)->hasProfile(1, function (array $attributes, User $user) {
return ['firstname' => $user->name];
})->create();
}
}
Could you give this a try:
public function definition()
{
$user = [
'name' => $this->faker->firstName,
'email' => $this->faker->unique()->safeEmail,
'active' => mt_rand(0, 1),
'role' => mt_rand(0, 5),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
'remember_token' => Str::random(10),
];
UserProfile::create([
'user_id' => $user->id
//any other extra data you have in the user_profiles table
]);
return $user;
}
You need to use for method, Belongs To Relationships
UserProfile::factory()
->for(User::factory()->state([
'name' => 'name', // optional
...
]), 'profile')->state([
'firstname' => 'firstname', // optional
...
])->create();
or
$users = User::factory()->count(100)->create();
foreach ($users as $key => $user) {
UserProfile::factory()
->for($user, 'profile')
->create();
}
I have setup laravel and used it's default authentication controller but I modified the table name and it's table structure and accordingly I also changed the RegisterController and LoginController. And the RegisterController is working fine and registering a new user but when ever I try to login using the login form it gives the same validation error of "These credentials do not match our records."
I have attached the following files: LoginController, RegisterController, Admin(Model), Config->auth
I have overridden the username field according to my EmailAddress field.
Admin Model
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
class admin extends Authenticatable
{
use Notifiable;
public $table = 'admin';
public $timestamps = false;
protected $primaryKey = 'AdminId';
protected $fillable = ['FirstName', 'LastName', 'FirstName_ar','LastName_ar','EmailAddress','Password','IsActive','remember_token'];
protected $hidden = ['Password', 'remember_token'];
public function getAuthPassword()
{
return $this->Password;
}
}
Login Controller
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Auth;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function username()
{
return 'EmailAddress';
}
public function getRememberTokenName()
{
return "remember_token";
}
}
Register Controller
<?php
namespace App\Http\Controllers\Auth;
use App\admin;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'firstname' => 'required|string|max:255',
'lastname' => 'required|string|max:255',
'firstname_ar' => 'required|string|max:255',
'lastname_ar' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'password' => 'required|string|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return admin::create([
'FirstName' => $data['firstname'],
'LastName' => $data['lastname'],
'FirstName_ar' => $data['firstname_ar'],
'LastName_ar' => $data['lastname_ar'],
'EmailAddress' => $data['email'],
'Password' => bcrypt($data['password']),
'IsActive' => 1,
'remember_token' => str_random(10)
]);
}
public function getRememberTokenName()
{
return $this->remember_token;
}
}
Config->auth.php
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'admin',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'admin',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
// 'users' => [
// 'driver' => 'eloquent',
// 'model' => App\User::class,
// ],
'admin' => [
'driver' => 'eloquent',
'model' => App\admin::class,
],
],
'passwords' => [
// 'users' => [
// 'provider' => 'users',
// 'table' => 'password_resets',
// 'expire' => 60,
// ],
'admin' => [
'provider' => 'admin',
'table' => 'password_resets',
'expire' => 60,
],
],
];
In the RegisterController, in the create method, instead of
'password' => bcrypt($data['password']), do this
'password' => Hash::make($data['password'])
Probably why your error is happening because maybe when you're registering you're using the bcrypt hashing method for the password but when you're logging, it's using a different hashing method.
Make sure to import the class
use Illuminate\Support\Facades\Hash;
at the top of your RegisterController file.
One more thing to take care of here is to make sure when you're inserting the new user record in the database, make sure to lowercase the email by default and when logging, make sure to lowercase the email too. Some databases are case sensitive by default. So you may have a problem there.
Like you have an email in the database,
Admin#example.com and when logging, you give admin#example.com, it will not match in that case.
Hope this helps.
I am using the Laravel multi-auth for multiple users.
I have frontend controller for the public access where no login is required. I want to check there if the user is logged in. If so I want to hide Login nav and show Home/Dashboard nav link which on click should redirect users to his dashboard.
How can I check this in front-end controller/view? Any help is appreciated.
Thanks in advance.
I have following guards:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'university' => [
'driver' => 'session',
'provider' => 'universities',
],
'school' => [
'driver' => 'session',
'provider' => 'schools',
],
'student' => [
'driver' => 'session',
'provider' => 'students',
],
],
Model:
<?php
namespace Modules\Student\Http\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Student extends Authenticatable
{
use Notifiable;
protected $guard = 'student';
protected $fillable = ['first_name', 'last_name', 'email', 'password', 'remember_token'];
public function applications()
{
return $this->hasMany("Modules\Student\Http\Models\Application", 'student_id');
}
public function languages()
{
return $this->hasMany("Modules\Student\Http\Models\StudentLanguage", 'student_id');
}
public function certificates()
{
return $this->hasMany("Modules\Student\Http\Models\StudentCertificate", 'student_id');
}
public function educations()
{
return $this->hasMany("Modules\Student\Http\Models\StudentEducation", 'student_id');
}
}
Controller:
<?php
namespace Modules\Student\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Modules\Admin\Http\Models\Country;
use Modules\Student\Http\Models\Student;
use Modules\Student\Http\Models\Application;
use Modules\Student\Http\Models\StudentCertificate;
use Modules\Student\Http\Models\StudentLanguage;
use Modules\Student\Http\Models\StudentDocument;
use Modules\Student\Http\Models\StudentEducation;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Storage;
class StudentController extends Controller
{
protected $redirectTo = '/student';
public function __construct()
{
$this->middleware('auth:student');
}
public function index()
{
return view('student::dashboard');
}
public function profileForm()
{
$countries = Country::get(['id', 'country_name'])->toArray();
$student = Student::with('languages')
->with('certificates')
->with('educations')
->with('educations.country')
->with('ducuments')
->find(Auth::User()->id);
$student->countries = $countries;
$student->docsGroup = $student->ducuments->groupBy('doc_type');
return view('student::student_profile')
->withStudent($student);
}
public function deleteEducation($id)
{
$language = StudentEducation::find($id);
if($language->delete()){
return 'success';
}
}
public function addCertificate(Request $request)
{
$this->validate($request, [
'certificate_name' => 'required',
'certificate_score' => 'required',
]);
$certificate = new StudentCertificate();
$certificate->student_id = Auth::id();
$certificate->certificate_name = $request->certificate_name;
$certificate->score = $request->certificate_score;
if($certificate->save()){
Session::flash('success', 'New certificate added successfully!');
return redirect()->route('student.profile');
};
Session::flash('success', 'Some error occured while addeding certificate!');
return redirect()->back()
->withInput()->with('tab', ['basic_info']);;
}
}
And this is my controller where I want to check if any student/admin.. logged in or not:
<?php
namespace Modules\Student\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Modules\Admin\Http\Models\Degree;
use Modules\Admin\Http\Models\ProgramCategory;
use Modules\University\Http\Models\Program;
use Modules\University\Http\Models\Scholarship;
use Modules\University\Http\Models\University;
use Modules\Admin\Http\Models\Country;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
class FrontendController extends Controller
{
// public function __construct()
// {
// $this->middleware('auth:student');
// }
public static function GetSearchAttributes()
{
$country_ids = University::where([
['status', '=', 'active'],
['id', '>', '0']
])
->get(['country_id'])
->pluck('country_id')
->toArray();
$countries = Country::orderBy('country_name', 'asc')
->whereIn('id', $country_ids)
->get(['id', 'country_name'])
->toArray();
$categories = ProgramCategory::orderBy('category_name', 'ASC')
->with('ProgramsCount')
->where([
['status', '=', 'active'],
['parent_id', '=', null]
])
->get(['category_name', 'id'])
->toArray();
$degrees = Degree::orderBy('degree_name', 'asc')
->where('status', '=', 'active')
->get(['degree_name', 'id'])
->toArray();
$searchAttr['countries'] = $countries;
$searchAttr['categories'] = $categories;
$searchAttr['degrees'] = $degrees;
$searchAttr = (object) $searchAttr;
return $searchAttr;
}
/**
* Display a listing of the resource.
* #return Response
*/
public function index()
{
$logos = University::orderBy('id', 'ASC')
->where([
['status', '=', 'active']
])
->limit(8)
->get();
return view('student::index')->withLogos($logos);
}
Use check()
#if (Auth::guard('student')->check())
///show link for student
#elseif(Auth::guard('admin')->check())
//show link for admin
#else
///show login
#endif
Do this for other guards too. See this for better understanding.
I am using Laravel 5.1 and I need multiple login in my project so I am trying Kbwebs\MultiAuth and Sarav\Multiauth for multi auth, both are worked with user model model but unfortunately when I use TenderApplicant model Auth::attempt return false every time.
This is my code:
app.php
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Foundation\Providers\ArtisanServiceProvider::class,
Illuminate\Auth\AuthServiceProvider::class,
Sarav\Multiauth\MultiauthServiceProvider::class,
...
auth.php
return [
'multi' => [
'admin' => [
'driver' => 'eloquent',
'model' => App\User::class,
'table' => 'sa_users',
],
'user' => [
'driver' => 'eloquent',
'model' => App\Models\TenderApplicant::class,
'table' => 'tender_applicant',
],
],
'password' => [
'email' => 'emails.password',
'table' => 'sa_password_resets',
'expire' => 60,
],
];
AuthController.php
class AuthController extends Controller
{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
public function __construct()
{
$this->middleware('guest', ['except' => 'getLogout']);
}
public function userAuth(Request $request)
{
$this->validate($request, ['email' => 'required','password' => 'required']);
$email = $request->input('email');
$password = $request->input('password');
var_dump(Auth::attempt("user", ['email' => 'awal.ashu#gmail.com', 'password' => '123456']));
}
return false for user but admin worked perfected.
TenderApplicant.php
namespace App\Models;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class TenderApplicant extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'tender_applicant';
protected $primaryKey = 'TE_APP_ID';
const CREATED_AT = 'CREATED_AT';
const UPDATED_AT = 'UPDATED_AT';
protected $fillable = [
'TENDER_ID',
'SCHEDULE_ID',
'PR_DETAIL_ID',
'NID',
'PR_CATEGORY',
'PR_TYPE',
'APPLICANT_NAME',
'EMAIL',
'APPLICANT_PHONE',
'PASSWORD',
'HOLDING_NO',
'IS_TE_SC_BOUGHT',
'TE_SC_AMOUNT',
'TE_SC_DATE',
'SPOUSE_NAME',
'BID_AMOUNT',
'BG_AMOUNT',
'BG_AMOUNT_TEXT',
'BANK_ID',
'B_DRAFT_NO',
'B_DRAFT_DATE',
'B_DRAFT_ATTACHMENT',
'IS_SELECTED',
'IS_ACTIVE',
'CREATED_BY',
'UPDATED_BY'
];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $guarded = ['TE_APP_ID'];
/**
* Password need to be all time encrypted.
*
* #param string $password
*/
public function setPasswordAttribute($password)
{
$this->attributes['PASSWORD'] = bcrypt($password);
}
}
By default, Laravel excepts you to keep password field as "password". In case you change(you have kept as PASSWORD), you have to inform Laravel about your password field change.
Please add the following code to your TenderApplicant.php file and check
public function getAuthPassword()
{
return $this->PASSWORD;
}
And then try accessing like the following,
Auth::attempt('admin', ['EMAIL' => 'youremail#gmail.com', 'password' => 'your_password']);
NOTE : You don't have to change your password as PASSWORD in here, because we have defined our method in model.
When you try attempting Auth::attempt(), laravel will run following query
SELECT * FROM "your_auth_table" WHERE email = "given_email" LIMIT 1
Then with the obtained result, laravel will take password field from the obtained result which will be hash.
Then it will call getAuthPassword() method from model and get the password field you have provided. By default it will be "password". Now with php function
password_verify
, laravel will verify your hash password with user given plain text and initiate user session
For more information you can check this blog.
http://blog.sarav.co/laravel-password-management-mechanism/