I have created separate table called subscribers in mysql changed config/auth.php settings to 'model' => App\Subscribers::class, 'table' => 'subscribers'.
I have login form on home page, that submits to the home page.
so in routes i have below
Route::get('/', function () {
return view('home');
});
Route::post('/', 'LoginController#validate');
my LoginController
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
public function validate()
{
// attempt to do the login
$auth = Auth::attempt(
[
'email' => strtolower(Input::get('email')),
'password' => Hash::make(Input::get('password'))
]
);
if ($auth) {
return Redirect::to('dashboard');
}
}
}
when i login i get below error
Declaration of App\Http\Controllers\LoginController::validate() should be compatible with App\Http\Controllers\Controller::validate(Illuminate\Http\Request $request, array $rules, array $messages = Array, array $customAttributes = Array)
You can't use 'validate' as a name for a function. It will conflict with:
App\Http\Controllers\Controller::validate
Also add an 'else' to your if statement so if your authentication fails you can redirect the user back to the login screen for example.
Related
After a huge search in the internet and in the forum, I just gave up...
I am develping a rest api using Laravel 8 and I am trying since week to make the email verification working using the officiel documentation for that, the email is always sent successfully once the user is registered event(new Registered($user));
The problem is that once I click on the link in the received email, I got redirected to the login page (which in this case is a post call)..
Here my routes/api.php:
Route::group(['namespace' => 'App\Http\Controllers', 'middleware' => ['api'], 'prefix' => 'auth'], function ($router) {
Route::post('login', 'AuthController#login')->name('login');
Route::post('register', 'AuthController#register');
Route::post('logout', 'AuthController#logout');
Route::post('profile', 'AuthController#profile')->middleware('verified');
Route::post('refresh', 'AuthController#refresh');
});
Route::group(['namespace' => 'App\Http\Controllers', 'middleware' => ['api']],function ($router) {
Route::get('/email/verify/{id}/{hash}', 'VerificationController#verify')->middleware(['auth', 'signed'])->name('verification.verify');
Route::get('/email/resend', 'VerificationController#resend')->middleware(['auth', 'throttle:6,1'])->name('verification.send');
});
And here my VerificationController:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
class VerificationController extends Controller
{
public function resend(Request $request)
{
$request->user()->sendEmailVerificationNotification();
return response()->json(['message' => __('auth.email_sent')], Response::HTTP_NO_CONTENT);
}
public function verify(EmailVerificationRequest $request)
{
$request->fulfill();
return response()->json(['message' => __('auth.user_verified_successfully')], Response::HTTP_RESET_CONTENT);
}
}
Last but not least, I added the LogVerifiedUser event to EventServiceProvider as required.
Any suggestion plz? I tried to remove the middleware auth from verify route, but it doesn't help me...
PS: I am using JWT for authentication
I had to develop exactly the same functionality for my rest laravel 8 api, I share my work with you, hoping to be able to help you.
To begin, your problem is that the user is redirected to the login page after clicking on the verification link. But the question is has the user been marked as verified in the database when he click ?
If it is marked as verified in the database after the click, the functionality is working but the problem is the redirection. Because if you are using a Rest API you would probably want the user to be redirected to a login or success page of your frontend application.
The last problem is your middleware. First in the api.php file the middleware for the connection is 'auth:api' instead of 'auth'. But for once you do not have to put middleware on the verification route otherwise you will have to have the user connect so that he validates his email and since you go through an API route it is pretty boring ...
Finally here is the solution I opted for :
1. In your app/Models/User.php implements MustVerifyEmail (Normally, from what I understood, that you already did, but I prefer to put it in case if other people go through this topic)
<?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\Passport\HasApiTokens;
class User extends Authenticatable implements MustVerifyEmail
{
use HasFactory, Notifiable, HasApiTokens;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
2. In your app/Http/Controllers/AuthController.php add event on registered user (Normally, from what I understood, that you already did, but I prefer to put it in case if other people go through this topic)
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Auth\Events\Registered;
class AuthController extends Controller
{
public function register(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|max:55',
'email' => 'email|required|unique:users',
'password' => 'required|confirmed'
]);
$validatedData['password'] = bcrypt($request->password);
$user = User::create($validatedData);
event(new Registered($user));
$accessToken = $user->createToken('authToken')->accessToken;
return response(['user' => $user, 'access_token' => $accessToken]);
}
public function login(Request $request)
{
$loginData = $request->validate([
'email' => 'email|required',
'password' => 'required'
]);
if (!auth()->attempt($loginData)) {
return response(['message' => 'Invalid Credentials']);
}
$accessToken = auth()->user()->createToken('authToken')->accessToken;
return response(['user' => auth()->user(), 'access_token' => $accessToken]);
}
}
3. In your routes/api.php defines this routes :
// Verify email
Route::get('/email/verify/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
// Resend link to verify email
Route::post('/email/verify/resend', function (Request $request) {
$request->user()->sendEmailVerificationNotification();
return back()->with('message', 'Verification link sent!');
})->middleware(['auth:api', 'throttle:6,1'])->name('verification.send');
4. Create app/Http/Controllers/VerifyEmailController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Auth\Events\Verified;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use App\Models\User;
class VerifyEmailController extends Controller
{
public function __invoke(Request $request): RedirectResponse
{
$user = User::find($request->route('id'));
if ($user->hasVerifiedEmail()) {
return redirect(env('FRONT_URL') . '/email/verify/already-success');
}
if ($user->markEmailAsVerified()) {
event(new Verified($user));
}
return redirect(env('FRONT_URL') . '/email/verify/success');
}
}
Explanations:
With this solution we keep all the operation of checking the official documentation by email. Except that instead of checking if the user is connected to retrieve it and put his email in verified. We launch a method in a controller which will find the corresponding user to put it in verified.
I hope I was understandable and that it can help you :)
That's because in register() method you don't logged in the user immediately after registering the user, when the user click the link in the email, laravel auth middleware detect that current user who visit the link is not authenticated, so it redirect the user to login route. To solve this problem refer to #Matthieu Gelle answer but customizes it as follows:
in step number 2 just add this code
Auth::login($user);
below event(new Registered($user));
in step 3 use this middleware:
->middleware(['auth', 'signed'])->name('verification.verify');
for those who use sanctum:
->middleware(['auth:sanctum', 'signed'])->name('verification.verify');
and change method name from '__invoke' to 'verifyEmail'
in step 4 use this method:
public function verifyEmail(\Illuminate\Foundation\Auth\EmailVerificationRequest $request)
{
$request->fulfill();
return response()->json(['code' => 200, 'message' => "Verified successfully"], 200);
}
I need to check if I have all posted variables are required or else throw error.
Till Now I am doing like this
Routes.php
Route::post('/api/ws_fetchuser', 'UserController#fetch_user_details');
UserController.php
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\User;
class UserController extends Controller
{
public function fetch_user_details(Request $request)
{
if(!empty($request) && $request->id!='')
{
print_r($request->id);
}
else
{
return response(array(
'error' => false,
'message' =>'please enter all form fields',
),200);
}
}
}
I am checking like this $request->id!='', is there any validation rules or methods which I can use to check id is required field.
I have added this validation in my controller as well but what if id is not present how can I show the error?
Updated Validation Code:
public function fetch_user_details(Request $request)
{
$this->validate($request, [
'id' => 'required'
]);
print_r($request->id);
}
$this->validate() methods designed to redirect back when validation failed, So instead of that you can create a validator instance and get the error list manually.
use Validator;
$validator = Validator::make($request->all(), [
'id' => 'required'
]);
if ($validator->fails()) {
return json_encode($validator->errors()->all());
}
Hello I'm trying to create a code generator to invite a user from input email, I want to save on the database the user id who send the invite, the code, and the email who is going to recive the invite, but I can't get the id of my auth user doing $request->user('id') (not working) also I know there is other method to do this easier than using DB::table something like
$request->user()->invites()->create... my controller looks like
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class invitacionController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index(Request $request)
{
return view('administrar');
}
public function invitacion(Request $request)
{
$this->validate($request, [
'email' => 'required|email|max:255|unique:invites',
]);
/*$request->user()->invites()->create([
'code' => str_random(40),
]);*/
DB::table('invites')->insert([
['usuId' => $request->user('id'), 'code' => str_random(40), 'email' => $request->input('email')],
]);
return redirect('/administrar');
}
}
If the relationship is properly configured, the first (commented) method should be working.
As for the second method, I think you are adding extra brackets:
DB::table('invites')->insert([
'usuId' => $request->user()->id, // <---
'code' => str_random(40),
'email' => $request->input('email')
]);
That hasMany method can take additional parameters. By default it expects the column to be named user_id, but you called it usuId. The documentation gives this example:
return $this->hasMany('App\Comment', 'foreign_key');
So I think you should do
public function invites()
{
return $this->hasMany(Invite::class, 'usuId');
}
How to override Laravel 5.1 auth attempt with extra parameters using default auth controller and middleware?
suppose I have an extra field with status =active or inactive.
How can I write that attempt method?
As specified in the documentation you can pass an array of variables, with their keys being the columns you want to verify the values against in the database.
<?php
namespace App\Http\Controllers;
use Auth;
use Illuminate\Routing\Controller;
class AuthController extends Controller {
public function authenticate(Request $request)
{
$attempt = Auth::attempt([
'email' => $request->get('email'),
'password' => $request->get('password'),
'active' => $request->get('active')
]);
if ($attempt) {
return redirect()->intended('dashboard');
}
}
}
I have made an Admin Interface(A very simple Admin Interface).But if i want to login as an admin,i can not able to logged in as an admin though my username and password is absolutely right.
My Admin Controllers resides,
app/
controller/
Admin/
AdminController.php
And My views resides
app/
views/
admin/
Admin-login.blade.php
and i have created routes something like this
Route::get('admin',array(
'as' => 'admin',
'uses' =>'Admin\AdminController#AdminLogin'
));
Route::group(array('before' => 'auth'),function(){
//These Urls are Intended page after Admin Sign In
Route::get('marriage-admin/',array(
'as' => 'marriage-admin',
'uses' => 'MarriageController#MarriageAdmin'
));
Route::post('edit-marital-data',array('as' => 'edit-marital-data','uses' => 'MarriageController#EditMarritalStatus'));
Route::post('searched-marital-data',array('as' => 'searched-marital-data','uses' => 'MarriageController#SearchMarriage'));
}
Route::group(array('before' => 'guest'),function(){
/* CSRF Protect*/
Route::group(array('before' => 'csrf'),function(){
Route::post('admin-marriage',array(
'as' => 'admin-marriage',
'uses' => 'Admin\AdminController#AdminLoginPost'
));
}
}
and this is my Admin Controller
<?php
namespace Admin;
class AdminController extends \BaseController{
public function AdminLogin(){
return \View::make('admin.login');
}
public function AdminLoginPost(){
$auth=\Auth::attempt(array(
'username' => \Input::get('username'),
'password' => \Input::get('password')
));
if($auth){
return \Redirect::intended('marriage-admin');
}else{
return \Redirect::route('admin')->with('global','The username or password you provided is wrong!');
}
return Rediret::route('admin')->with('global','Please Review Your Admin Database.');
}
}
?>
and i have also created a Admin.php model since i have a different table namely admins in my database.
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class Admin extends Eloquent implements UserInterface, RemindableInterface {
public function getRememberToken()
{
return $this->remember_token;
}
public function setRememberToken($value)
{
$this->remember_token = $value;
}
public function getRememberTokenName()
{
return 'remember_token';
}
/*public static function blood_search($blood_group){
return static::where('blood_group','LIKE','%'.$blood_group.'%');
} */
protected $table = 'admins';
protected $fillable=array
( 'username',
'password'
);
use UserTrait, RemindableTrait;
}
in mention, page after login or you can say the dash bored of the Admin is taken from another controller namely MarriageController
Now if i try to logged in as an Admin.
i am getting the message
The username or password you provided is wrong!
which i have set in my Admin Controller, if auth is fail.
So why i am getting this message though the username and password i am providing is absolutely right ?
now my question is,am i missing some configuration for Admin??
Laravel doesn't use md5 encryption. While creating a user you need to Hash password using laravel Hash::make()
User::create(array(
'username' => Input::get('username'),
'password' => Hash::make(Input::get('password'))
));
If you want to manually insert it to database then
return Hash::make('yourpass');
then paste the returned result.