When I register a new user and I want to sign him in by using auth attempt it doesn't work while the user is saved to database
static function register()
{
if(self::$validate['message'])
{
$user = User::create([
'name' => self::$values['name'],
'email' => self::$values['email'],
'password' => Hash::make(self::$values['password'])
]);
Auth::attempt($user,true);
Auth::attempt($user->only(['email','password']));
return result::repsonse(true);
} else
return self::$validate;
}
You can use Auth::login() method
static function register()
{
if(self::$validate['message'])
{
$user = User::create([
'name' => self::$values['name'],
'email' => self::$values['email'],
'password' => Hash::make(self::$values['password'])
]);
Auth::login($user);
return result::repsonse(true);
} else
return self::$validate;
}
I was recently updating from laravel's sanctum to passport; and there is this one test that bothers me a lot.
In sanctum there is this method under the PersonalAccessToken model that finds the token and returns the token if it exists.
I don't seem to find anything like that in the docs or online.
I'm validating the test by asserting that $user->tokens is not empty... yet I wish to validate that the token I'm returning from my login controller is indeed a token; not just the creation;
Thnx in advance...
Login Test
public function user_can_login()
{
//$this->withoutExceptionHandling();
$user = User::factory()->create();
$url = route('api.v1.auth.login', [
'email' => $user->email,
'password' => 'password'
]);
$res = $this->jsonApi()
->post($url)
->assertStatus(200);
$token = $res->json(['access_token']);
$this->assertNotEmpty($user->tokens);
}
Login method in authcontroller
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$credentials = $request->only(['email', 'password']);
if (Auth::attempt($credentials)) {
$user = Auth::user();
$access_token = $user->createToken('laravel-api.local')->accessToken;
return response()->json(['access_token' => $access_token], 200);
} else {
return response()->json(['error' => 'Unauthorized'], 401);
}
}
pues:dont know why im writing the code, but just for ref of what i'm doing
https://laracasts.com/discuss/channels/testing/how-do-i-create-a-route-while-testing
solution is quite simple... you'll find it here... I had an issue when I tried that before hand and it seems to be with the use of the Route::name('name') method and the route('name') function threw a server error. but if you call the path directly it should work...
any who... authController and login method stay the same but the test changes to...
public function setUp(): void
{
parent::setUp();
Route::middleware('auth:api')
->get('/test-route', function (Request $request) {
return $request->user();
});
$clientRepository = new ClientRepository();
$client = $clientRepository->createPersonalAccessClient(
null,
'Personal Access Client Test',
'/'
);
DB::table('oauth_personal_access_clients')->insert([
'client_id' => $client->id,
'created_at' => date('Y-m-d'),
'updated_at' => date('Y-m-d'),
]);
}
/** #test */
public function user_can_login_with_correct_credentials()
{
//$this->withoutExceptionHandling();
$user = User::factory()->create();
$url = route('api.v1.auth.login', [
'email' => $user->email,
'password' => 'password',
'device_name' => $user->name . ' test Device'
]);
$res = $this->jsonApi()
->post($url)
->assertStatus(200);
$token = $res->json(['access_token']);
$this->jsonApi()
->withHeader('Authorization', 'Bearer ' . $token)
->get('/test-route')
->assertStatus(200);
}
I have a custom guard set up for 'customer' which has a LoginController that works absolutely fine. The login controller is as follows:
public function login(Request $request)
{
// Validate form data
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:6'
]);
// Attempt to log the user in
if(Auth::guard('customer')->attempt(['email' => $request->email, 'password' => $request->password], $request->remember))
{
return redirect()->intended(route('customer.dashboard'));
}
// if unsuccessful
return redirect()->back()->withInput($request->only('email','remember'))
}
Now, within my workflow in another route where I check out customers; I have another controller where I create a new customer. I then attempt to log them in since I have all their details, this doesn't seem to work, does anyone have any idea on what I am doing wrong?
public function registerCustomer($data)
{
$pw = Hash::make($data->pw->main);
$customer = new Customer;
$customer->firstname = $data->customer->name;
$customer->lastname = $data->customer->lastname;
$customer->mobile = $data->customer->mobile;
$customer->email = $data->customer->email;
$customer->password = $pw;
$customer->save();
//I HAVE TRIED THIS
// if(Auth::guard('customer')->attempt(['email' => $data->customer->email, 'password' => $pw]))
// {
// dd('logged in');
// }
//AND NOW THIS...
$logged = Auth::guard('customer')->attempt([ 'email' =>$data->customer->email, 'password' => $pw ]);
dd($logged);
}
In registerCustomer function, $pw is an encrypted password. You could not use it for Auth::guard('customer'). You have to replace $pw by $data->pw->main.
$logged = Auth::guard('customer')->attempt([ 'email' =>$data->customer->email, 'password' => $data->pw->main ]);
dd($logged);
so I have this store function at my Controller
public function store(Request $request)
{
Penghuni::create([
'nama_penghuni' => $request->nama_penghuni,
'email' => $request->email,
'phone' => $request->phone,
'tower' => $request->tower,
'no_unit' => $request->no_unit
]);
User::create([
'name' => $request->nama_penghuni,
'email' => $request->email,
'password' => Hash::make($request['password']),
'role' => 'penghuni',
]);
return redirect(route('penghuni.index'));
}
what I want is make sure both insert is success, because the current result I got is when Penghuni create is done but the user is fails it keeps getting redirected
hope someone can help, I use laravel 5.8
thank you
This Code is Perfect check other things.
public function store(Request $request)
{
Penghuni::create([
'nama_penghuni' => $request->nama_penghuni,
'email' => $request->email,
'phone' => $request->phone,
'tower' => $request->tower,
'no_unit' => $request->no_unit
]);
User::create([
'name' => $request->nama_penghuni,
'email' => $request->email,
'password' => Hash::make($request['password']),
'role' => 'penghuni',
]);
return redirect(route('penghuni.index'));
}
1. Model
Penghuni and user Model must added this Line
protected $guarded = [];
Other Solution
public function store(Request $request)
{
$penghuni = new Penghuni;
$penghuni->nama_penghuni = $request->nama_penghuni;
$penghuni->email = $request->email;
$penghuni->phone = $request->phone;
$penghuni->tower = $request->tower;
$penghuni->no_unit = $request->no_unit;
$penghuni->save();
$user = new User;
$user->name = $request->nama_penghuni;
$user->email = $request->email;
$user->password = Hash::make($request->password);
$user->role = 'role';
$penghuni->users()->save($user);
return redirect(route('penghuni.index'));
}
You can wrap your queries in a database transaction like so:
DB::transaction(function () use ($request) {
// queries here
});
return redirect(route('penghuni.index'));
Or something like this, depending on your use-case.
DB::beginTransaction();
try {
// queries here
// all good
DB::commit();
return redirect(route('penghuni.index'));
} catch (\Exception $e) {
// something went wrong
DB::rollback();
}
You can read more about database transaction here: https://laravel.com/docs/8.x/database#database-transactions
I have some problem when I want to make login, I got an issue for my Auth::attempt always false value, Is am I got something wrong in my code?
Controller :
public function register(Request $register)
{
$validator = Validator::make($register->all(), [
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
]);
if ($validator->fails()) {
return response()->json(['error' => $validator->errors()], 401);
} else {
$name = $register->input('name');
$email = $register->input('email');
$pwd = $register->input('password');
$c_pwd = $register->input('c_password');
// Crypting password & c_password to md5
$md5_pwd = md5($pwd);
$md5_c_pwd = md5($c_pwd);
// Salt password & c_password
$password = crypt($md5_pwd, "asd");
$c_password = crypt($md5_c_pwd, "asd");
$data = new User();
if ($password == $c_password) {
$user = User::create([
'name' => $name,
'email' => $email,
'password' => $password,
]);
$success['token'] = $user->createToken('SSOApp')->accessToken;
return response()->json([
'success' => true,
'token' => $success,
'user' => $user
]);
} else {
return response()->json(['error' => "Password doesn't match"], 401);
}
}
}
public function login()
{
$email = request('email');
$pwd = request('password');
$md5 = md5($pwd);
$password = crypt($md5, "asd");
if (Auth::attempt(['email' => $email, 'password' => $password])) {
$user = Auth::user();
$success['token'] = $user->createToken('SSOApp')->accessToken;
return response()->json([
'success' => true,
'token' => $success,
'user' => $user
]);
} else {
return response()->json([
'success' => false,
'message' => 'Invalid Email or Password',
], 401);
}
}
I assume you messed up with Laravel Default Password Hashing System
public function register(Request $register)
{
$validator = Validator::make($register->all(), [
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
'c_password' => 'required|same:password',
]);
if ($validator->fails()) {
return response()->json(['error' => $validator->errors()], 401);
} else {
$name = $register->input('name');
$email = $register->input('email');
$pwd = $register->input('password');
$c_pwd = $register->input('c_password');
// $data = new User();
$user = User::create([
'name' => $name,
'email' => $email,
'password' => bcrypt($password . 'salt'),
]);
$success['token'] = $user->createToken('SSOApp')->accessToken;
return response()->json([
'success' => true,
'token' => $success,
'user' => $user
]);
}
}
public function login()
{
$email = request('email');
$pwd = request('password');
if (Auth::attempt(['email' => $email, 'password' => $password . 'salt'])) {
$user = Auth::user();
$success['token'] = $user->createToken('SSOApp')->accessToken;
return response()->json([
'success' => true,
'token' => $success,
'user' => $user
]);
} else {
return response()->json([
'success' => false,
'message' => 'Invalid Email or Password',
], 401);
}
}
Try this code. I don't know what happened to your code about the password you tried to encrypt it in attempt.
public function login(LoginRequest $request) {
if(!Auth::attempt([
'email' => $request->email,
'password' => $request->password,
'active' => true
])) {
return response()->json('Email or Password is incorrect', 500);
}
$this->user = Auth::user()->load('roles');
return $this->createUserAccessTokenResponse();
}
protected function createUserAccessTokenResponse() {
return response()->json([
'status' => 'success',
'data' => [
'token' => $this->user->createToken($this->user->name)->accessToken,
'user' => $this->user
],
], 200);
}
your problem is that laravel by default hashes the password. so when you do Auth::attempt it's going to hash the password you provided. And the result is what you get, it will always false.
Instead, you need to Other Authentication Methods.
Auth::login($user);
// Login and "remember" the given user...
Auth::login($user, true);
Above is the easiest way to fix your code.
It's recommended to hash your password rather than encrypting the password.
Hashing password in laravel is also
Hash::make($password);
And then you can use Auth::attempt to log in your user.
Laravel Auth uses the bcrypt hashing when saving password via model you may use either of the 2 method
$account->password = bcrypt("YOUR_PASSWORD"); or $account->password = Hash::make("YOUR_PASSWORD");
Then if you're dealing with the auth attempt function, just simply call the method like this
if($account = Auth::attemp(['email' => "YOUR_EMAIL#DOMAIN.COM", 'password' => "YOUR_PASSWORD"])){
//success login, do your extra job here
}else{
//invalid credentials here
}
Instead of using md5 or crypt use \Hash::make() it is much secure
I refactored your code and it does the same thing
You only need to rename your c_password to password_confirmation
Source
Below code does the same thing that your code do
public function register(Request $register)
{
$this->validate($register, [
'name' => 'required',
'email' => 'required|email',
'password' => 'required|confirmed',
]);
$user = User::create([
'name' => $register->input('name'),
'email' => $register->input('email'),
'password' => $register->input('password'),
]);
$success['token'] = $user->createToken('SSOApp')->accessToken;
return response()->json([
'success' => true,
'token' => $success,
'user' => $user,
]);
}
public function login(Request $request)
{
$request->merge(['password' => \Hash::make($request->input('password'))]);
if (Auth::attempt($request->only(['email', 'password']))) {
$user = Auth::user();
$success['token'] = $user->createToken('SSOApp')->accessToken;
return response()->json([
'success' => true,
'token' => $success,
'user' => $user,
]);
}
return response()->json([
'success' => false,
'message' => 'Invalid Email or Password',
], 401);
}
when you hashing password using crypt it has a key to unlock it that's why there is a decrypt but when you use Hash::make() it doesn't have a key to break or unlock it, it will check it's algorithm to see if given password is matching the algorithm that already exists in the database that's why crypt is not safe and Hash::make is much much more safe