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.
Related
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 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
Laravel Passport has a very complex system for my app cause I think for this simple app it's very complex to have OAuth client's Id, Secret & ...
So I create a UserController myself to solve this complexity with these codes:
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use App\User;
use Response;
class UserController extends Controller
{
//
public function __construct(){
$this->content = array();
}
public function login(){
if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){
$user = Auth::user();
$this->content['token'] = $user->createToken('URL APP')->accessToken;
$status = 200;
}
else{
$this->content['error'] = "Unauthorised";
$status = 401;
}
return response()->json($this->content, $status);
}
}
but problem is every time user sign in get new tokens & old tokens won't expire & User with old tokens can send valid request (Its should be invalid I think).
Is there any way to config passport to users has one token or I should do it myself?
Yes its a problem with jwt tokens. But you can overcome this problem by making your own methods or by using some other libraries. "jwt-auth" is also a library for token and this also got the blacklist method you can use to blacklist a token.
or you can make a middleware in your routes and cache the token in redis or memcached database and save it against user_id and match it everytime with requests.
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