I am verifying user's account via email and I want to redirect the user directly to home page after account is verified.
The issue I am having is that I am not sure how to actually log in the user using login function.
class VerificationController extends Controller {
public function verify($token){
User::where('email_token',$token)->firstOrFail()->verified();
// auth()->login($user); works if $user exists
return redirect('/home');
}
}
Can I log in the user based on the email_token? I tried but it doesn't seem to work as expected.
You are on the right way. You just need to get the User instance and pass it to the login Method of the Auth class. I've made an example controller for you to show how this could be done.
class VerificationController extends Controller
{
public function verify($token)
{
// Fetch the user by the email token from the database.
// #firstOrFail returns the first matching user or aborts
// the request with a 404 error.
$user = User::where('email_token', $token)->firstOrFail();
// Activate your user or whatever this method does.
$user->verified();
// Logs the Client who did this web request into the
// User account fetched above in.
Auth::login($user);
// Redirect to wherever you want.
return redirect('/home');
}
}
Read more about authenticating users in the official documentation:
https://laravel.com/docs/authentication#other-authentication-methods
First, you have to configure login model in providers section in config/auth.php
Some changes have to made in login model also
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Authenticatable;
class ModelName extends Model implements \Illuminate\Contracts\Auth\Authenticatable
{
use Authenticatable;
}
and in your controller
if (!Auth::attempt(['username' => $username, 'password' => $password])) {
return redirect()->back()->with(['error' => 'Could Not Log You In!']);
} else {
return redirect()->route('routeName');
}
or did you ask to manually authenticate the user from a controller, here is the solution also
Auth::login($user);
where $user is the login model record of corresponding user
Related
I need to check in the rules (or authorize) if user can be authorized to delete his comment. ho can i do it? here's my rules
'user_id' => [
'required',
'exists:user,id',
],
I'm checking here if the user exists but how can i checked if user is the same as the logged one?
Right now I'm checking it in controller
public function destroy(CommentDestroyRequest $request, Comment $comment)
{
$userId = Auth::id();
if ($comment->user_id !== $userId)
return response()->json(null, Response::HTTP_FORBIDDEN);
}
but I wanted to move it
The context of the question is not correct. You are trying to use input validation to authorize users.
First; if you want to use logged in user's id to create a new record, you don't need to post it from a form, just use $request->user()->id or Auth::id() as you did. To make sure there is always an authenticated user; add auth middleware for that route (or controller method).
And on the other hand if you want to check if a user authorized to do something you should use authorization services which comes built-in with Laravel.
To accomplish that you can use Gate or Policy
Here is the documentation: https://laravel.com/docs/8.x/authorization
Let's say you want to determine if a user authorized to delete a Comment , you can do this by Writing Gates
You can define gates in your app/Providers/AuthServiceProvider.php file's boot method;
// app/Providers/AuthServiceProvider.php
use App\Models\Comment;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('delete-comment', function (User $user, Comment $comment) {
return $user->id === $comment->user_id;
});
}
Now you can use that gate with it's name -which is delete-comment here- to check authorization.
public function destroy(CommentDestroyRequest $request, Comment $comment)
{
if (Gate::denies('delete-comment', $comment)) abort(403);
// Authorization checked, you can do whatever you want
$comment->delete();
return redirect('/comments');
}
Or you can use authorize in a controller;
public function destroy(CommentDestroyRequest $request, Comment $comment)
{
$this->authorize('delete-comment', $comment);
// Authorization checked, you can do whatever you want
$comment->delete();
return redirect('/comments');
}
This will do the trick for you.
But a more convenient way to authorization in Laravel is Policies. You should definitely check and consider to use them.
Policies are classes that organize authorization logic around a
particular model or resource. For example, if your application is a
blog, you may have a App\Models\Post model and a corresponding
App\Policies\PostPolicy to authorize user actions such as creating
or updating posts.
You should save your user_id in comment section too so you can easily detect wether the user is authenticated or not
I set up a Laravel 8 installation with Jetstream and implemented a custom user registration, where an event is fired after a successful creation of the database record event(new Registered($user));.
The initial registration process should not require a password yet, because only a selected set of users should be able to login to a dashboard in the future.
After the registration the user gets an email with a verification link, however he still needs to login in order to get verified.
I tried to remove the auth middleware in routes/web.php, however i get an error message after attempting to verify a users email address.
Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
$request->fulfill();
return view('home');
})->middleware(['auth','signed'])->name('verification.verify');
Is it possible to verify a users email address without login information?
It is possible.
You can modify files directly in Jetstream packages however I will present method adding new files and keeping original packages untouched.
Add new Controller 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')); //takes user ID from verification link. Even if somebody would hijack the URL, signature will be fail the request
if ($user->hasVerifiedEmail()) {
return redirect()->intended(config('fortify.home') . '?verified=1');
}
if ($user->markEmailAsVerified()) {
event(new Verified($user));
}
$message = __('Your email has been verified.');
return redirect('login')->with('status', $message); //if user is already logged in it will redirect to the dashboard page
}
}
In web.php add a new route without auth middleware:
use App\Http\Controllers\VerifyEmailController;
...
Route::get('/email/verify/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
At the end clear routes cache:
php artisan route:cache
Open config/fortify.php file and uncomment the Features::emailVerification(), line.
'features' => [
Features::registration(),
Features::resetPasswords(),
// Features::emailVerification(),
Features::updateProfileInformation(),
Features::updatePasswords(),
Features::twoFactorAuthentication([
'confirmPassword' => true,
]),
],
Next go to the User modal and implement the MustVerifyEmail interface.
class User extends Authenticatable implements MustVerifyEmail{
use Notifiable;
}
Note: you should have knowledge about Mail in Laravel
I'm fairly new to Laravel and I'm currently working on a manual authentication for my project.
I have tried Auth::attempt to validate the credentials that have been input, and I have seen that it works since I am being redirected to the page I wanted when it is authenticated.
However, when I try to do Auth::check in the view I have been redirected to, it seems that it returns FALSE and does not read the authenticated user. This makes the certain portion of that view to not be visible. Any insights on this one? Thanks a lot!
Controller
namespace App\Http\Controllers;
use DB;
use Session;
use Illuminate\Http\Request;
use Auth;
class LoginController extends Controller
{ //
public function index()
{
return view('view_login');
}
public function verify(Request $request)
{
$credentials = $request->only('username', 'password');
if (Auth::attempt($credentials)) {
// Authentication passed...
return redirect('dashboard');
}
else
{
return redirect('/');
}
}
View
#if (Auth::check())
<li> Hello {{ Auth::user()->username }} </li>
#endif
Current Result:
Expected Result:
Update:
I've tried to put dd(auth()->user()); after authentication, and I have seen the attributes of the authenticated user. However, after putting this on the Dashboard Controller, it returns NULL. Can someone please help me on this?
Check the primary key of your users database. If you set your table's primary key other than id, you need to set it in your User model.
The Laravel Documentation states the following:
Eloquent will also assume that each table has a primary key column named id. You may define a protected $primaryKey property to override this convention.
For example, if you have a user_id column set as your primary key in your users database, you need to place the code below in the User model:
protected $primaryKey = 'user_id';
Actually your Authentication works fine, because you can print hello when user authenticated.
If you want to prevent access of unauthenticated user you can do this.
add this function as the first function of your controller
public function __construct()
{
$this->middleware('auth');
}
or you can check user in route
Route::get('admin/profile', function () {
//
})->middleware('auth');
by this ways just authenticated user can see the dashboard page.
Why don't you use Laravel's verification & write your own code in function authenticated instead.
FYI, function attemptLogin need to be call so that user can login.
I do my authentication via a restful API which I validate, if its successful it gives me the username and i take that and try to login to my Laravel app. When I finish logging in, it seems to work. However, It doesn't seem to be keeping session as I navigate around the site I am still authenticated as a guest.
public function login(){
// I do a guzzle request that gives me the value of $response['username']
$Username = $response['username'];
$user = User::where('username','thomc')->first();
Auth::login($user);
return view('home');
}
This is my User model:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $table = 'UserDetails';
}
My table:
Username
Email
First_Name
Last_Name
BA
Facebook_ID
Google_ID
Not sure if it's a test change, but you're not using the $Username, instead searching for the user thomc. Another thing to note would be check if the user with username exists in the database, if not the $user returned would be null. Try login with id as well.
$username = $response['username'];
$user = User::where('username', $username)->firstOrFail();
Auth::loginUsingId($user->id);
Also make sure all the routes are wrapped with the web middleware, and appropriate auth and guest middleware on routes as needed.
Consider below scenario.
There are 2 users who registered with the system.
If user 1 is logged in and tries to update User 2's profile. It should not be allowed.
I have tried it using Request class.
use App\Http\Requests\Request;
use Auth;
use App\User;
class ProfileRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
$routeUser = $this->route('userId');
if($routeUser->id == Auth::user()->id){
return true;
}
else{
abort(403);
}
}
}
Problem: It displays form with all information. It only blocks user when tries to update the info. How to block a user so that he/she cannot even view the form with data??
Use Laravel ACL to manage the role wise user access. By using role wise access only authorized user can access his/her account and do some stuff.
Laravel ACL documentation