I am having issues grabbing the currently authenticated user in Laravel 5.3. More specifically, I am making a HTTP request to my api.php file, which has the route defined as api/test/create.
The controller code:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Test;
class TestController extends Controller
{
public function store(Request $request) {
$this->validate($request, [
'test_name' => 'required',
'youtube_id' => 'required',
'is_live_test' => 'required',
]);
//Laravel 5.3 allows to get the user via request
$user = $request->user;
if($user) {
return 'We are logged in';
} else {
return 'We are not logged in';
}
return '';
}
}
Every time it returns 'We are not logged in'. To test this out, I referenced {{ Auth::check() }} in my blade file, and that returns as '1'. I am not quite sure why the Controller does not recognize the user is logged in; any ideas?
I have tried different variations of referencing the authentication, including importing the Facade and doing Auth::check(), Auth::user(), but it brings the same result regardless.
Get user object with:
$user = $request->user();
Or:
$user = auth()->user();
You can use:
Auth::user();
also
auth()->user();
also
$request->user();
You can use Auth::check() method directly in the Controller.
if (Auth::check()){
// User is logged in
// Do something with the Authenticated User.
}else
{
// User is not logged in
}
to get User Data do something like this
$user = Auth::user();
$userId = $user->id;
etc.
Related
The api I built with passport and laravel 8 does not logout by default.
I found a script, but it does not remove the entries in the oauth-access-tokens table
I added a function to the AuthController:
public function logout(Request $request){
$accessToken = auth()->user()->token();
$token= $request->user()->tokens->find($accessToken);
$token->revoke();
return response(['message'=> 'Je bent uitgelogd'], 200);
}
And added a path in api.php:
Route::post( 'logout', 'App\Http\Controllers\API\AuthController#logout')->middleware('auth:api');
When I try to logout with Postman, I get a success message, but the entry in the oauth-access-token table is not removed.
I intend to remove all tokens for the user, to log out from all devices
Can anyone tell me what I am doing wrong?
Change the logout function to be like:
public function logout(Request $request){
$user = Auth::user()->token();
$user->revoke();
return response(['message'=> 'Je bent uitgelogd'], 200);
}
This will log the user out from the current device where he requested to log out. If you want to log out from all the devices where he's logged in. Then do this instead:
use Laravel\Passport\RefreshToken;
use Laravel\Passport\Token;
public function logout(Request $request){
$tokens = $user->tokens->pluck('id');
Token::whereIn('id', $tokens)->update(['revoked', true]);
RefreshToken::whereIn('access_token_id', $tokens)->update(['revoked' => true]);
}
This will revoke all the access and refresh tokens issued to that user.
SOLVED:
I used the following code:
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
and the function:
public function logout(Request $request){
Auth::user()->tokens->each(function($token, $key) {
$token->delete();
});
return response(['message'=> 'Je bent uitgelogd'], 200);
}
So nothing is revoked, but all the tokens are just deleted..
If your are using passport,
Auth::user()->AauthAcessToken()->delete();
will remove all the tokens of the user.
In the AuthController i use this code
public function logout(Request $request) {
$request->user()->token()->revoke();
return response([
"message" => 'Session finished',
],200);
}
I need help for my Laravel application.
I use spatie roles and permissions.
When i create the user, assign roles is no problem. When i will update the same user, there is the following error:
[2019-12-06 08:44:36] local.ERROR: The given role or permission should use guard instead of `web`. {"userId":1,"exception":"[object] (Spatie\\Permission\\Exceptions\\GuardDoesNotMatch(code: 0): The given role or permission should use guard instead of web. at /home/vagrant/code/test/vendor/spatie/laravel-permission/src/Exceptions/GuardDoesNotMatch.php:12)
public function store(StoreUserRequest $request)
{
$user = $this->repo->create( $request->all());
$user->assignRole($request->roles);
return $user;
}
public function update(UpdateUserRequest $request, User $user)
{
$user = $this->repo->update($user, $request->all());
$user->assignRole($request->roles);
return $user;
}
I added protected $guard_name = 'web'; to the User Model but still the same problem.
What is wrong? Is there a problme with the userId?
On update method use syncRoles instead of assignRole
When you assign role for a user the model path App\User insert into table model_has_roles if you change the model folders spatie give you an error. I think this code may help you more.
don't missing add HasRoles
class User extends Authenticatable
{
use Notifiable, HasRoles;
...
}
make sure you import use App\User;
UserController
public function update(Request $request, $id)
{
$this->validate($request, [
'name' => 'required',
'email' => 'required|email|unique:users,email,'.$id,
'password' => 'same:confirm-password',
'roles' => 'required'
]);
$input = $request->all();
if(!empty($input['password'])){
$input['password'] = Hash::make($input['password']);
}else{
$input = array_except($input,array('password'));
}
$user = User::find($id);
$user->update($input);
DB::table('model_has_roles')->where('model_id',$id)->delete();
$user->assignRole($request->input('roles'));
return redirect()->route('users.index')
->with('success','User updated successfully');
}
Here is my controller that holds the store function
public function store(Request $request)
{
$artisan = Artisan::create($request->all() + ['user_id' => Auth::user()]);
return $artisan;
}
Can figure out why Auth::user() is pushing a null value to the db instead of picking the current authenticated user id.
please help guys.
Auth::user() returns a instance of the User class (if the user is logged in).
You have to pick the id from it, like this:
$user_id = Auth::user()->id;
To get user data from Auth::user(), you have to follow this.
You have to use Auth class for login.
if (Auth::attempt(['email' => $email, 'password' => $password])) {}
You have to include all the routes under web middleware where you want to access authenticated user data.
Route::group(['middleware' => ['web']], function () {
Route::post('/dashboard', 'Controller#dashboard');
}
As the value comes from Session and web middleware has Session
activated.
In laravel i have student,parent ,employee(Teacher,Librarian,warden) roles with different permissions...based on user role it should redirect to different blade files when user logged in..my problem is if user parent or student it is redirecting to different dashboards but whenever user is teacher or other it does not logged in but in users table already user exist.
below is my LoginController code
LoginController.php:
public function login(Request $request){
if(Auth::attempt([
'email'=>$request->email,
'username'=>$request->username,
'password'=>$request->password,
]))
{
$user=User::where('username',$request->username)->first();
$usertype=$user->user_type;
$username=$user->username;
$roles=DB::table('roles')->where('id','=',$usertype)->first();
$rolename=$roles->role_name;
if($rolename=="student"){
$student=DB::table('students')->where('stud_adm_id','=',$username)->first();
$classid=$student->class_id;
$sectionid=$student->section_id;
$class=DB::table('classtables')->where('id',$classid)->first();
$section=DB::table('sections')->where('id',$sectionid)->first();
return view('studentdashboard',compact('student','class','section'));
}elseif($rolename=="Teacher"){
$employeedetails=DB::table('employees')->where('employee_fname','=',$username)->first();
return view('teacherdashboard',compact('employeedetails'));
}
elseif($rolename=="parent"){
$parentdetails=DB::table('parents')->where('mother_phone','=',$username)->first();
$stateid=$parentdetails->state;
$state=DB::table('states')->where('state_id','=',$stateid)->first();
return view('parentdashboard',compact('parentdetails','state'));
}
}else{
return redirect()->back();
}
}
my roles are mentioned in role table and that id stored in users table
Thanks in advance...
You better create a middleware to check user role, and based on the role redirect user to different pages!
Run the command below to create a middleware that checks user's role.
php artisan make:middleware CheckRoleMiddleware
The command will create a file under App\Http\Middleware named CheckRoleMiddleware this class will come a predefined method handle() there you can place the logic that checks user's role and redirects them to different pages example:
<?php namespace App\Http\Middleware;
use Closure;
class CheckRoleMiddleware {
public function handle($request, Closure $next)
{
//User role is admin
if ( Auth::check() && Auth::user()->isAdmin() )
{
return $next($request);
}
//If user role is student
if(Auth::check() && auth()->user()->role === 'student')
{
return view('studentDashboard');
or route('routeName');
}
//If user role is teacher
if(Auth::check() && auth()->user()->role ==='teacher')
{
return view('teacherDashboard');
or route('routeName');
}
//default redirect
return redirect('home');
}
}
And don't forget to add CheckRoleMiddleware to App\Http\Kernel.php
protected $routeMiddleware = [
'auth' => 'App\Http\Middleware\Authenticate',
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
'user-role' => 'App\Http\Middleware\CheckRoleMiddleware', // this line right here
];
Lets just ignore everything about how this stuff should work and how it does by default and take what you have.
Do you see a problem here:
if ($rolename == "student")
elseif ($rolename == "Teacher")
elseif ($rolename == "parent")
If not, lets try it this way:
student
Teacher
parent
Which one is not like the others? And which one was the one that "was not working" correctly?
I would like to assume you have these roles named in a consistent fashion, so Teacher should be teacher.
You can do all of what you want to do with the default LoginController by overriding a method or two.
You should not be returning views from processing routes. POST REDIRECT GET. POST comes in, return a REDIRECT, that causes a GET request (which most likely is going to return a view).
For validating the login credentials:
protected function validateLogin(Request $request)
{
$this->validate($request, [
'email' => '...',
'username' => '...',
'password' => '...',
]);
}
For what credentials should be used from the request:
protected function credentials(Request $request)
{
return $request->only('email', 'username', 'password');
}
The response to return after successful authentication:
protected function authenticated(Request $request, $user)
{
// do your role checking here
// return a redirect response to where you want that particular user type to go
// return redirect()->route(...);
}
Everything related to building the views and gathering that data is its own route. All you have to do is return a redirect for the login flow. Where you redirect to is responsible for gathering the data needed to display a view.
I'm currently using 2 projects. 1 front end (with laravel backend to communicate with API) and another laravel project (the API).
Now I use Laravel Passport to authenticate users and to make sure every API call is an authorized call.
Now when I want to log out my user, I send a post request to my API (with Bearer token) and try to log him out of the API (and clear session, cookies,...)
Then on the client I also refresh my session so the token is no longer known. Now when I go back to the login page, it automatically logs in my user. (Or my user is just still logged in).
Can someone explain me how to properly log out a user with Laravel passport?
Make sure that in User model, you have this imported
use Laravel\Passport\HasApiTokens;
and you're using the trait HasApiTokens in the User model class using
use HasApiTokens
inside the user class.
Now you create the log out route and in the controller,
do this
$user = Auth::user()->token();
$user->revoke();
return 'logged out'; // modify as per your need
This will log the user out from the current device where he requested to log out. If you want to log out from all the devices where he's logged in. Then do this instead
$tokens = $user->tokens->pluck('id');
Token::whereIn('id', $tokens)
->update(['revoked'=> true]);
RefreshToken::whereIn('access_token_id', $tokens)->update(['revoked' => true]);
Make sure to import these two at the top
use Laravel\Passport\RefreshToken;
use Laravel\Passport\Token;
This will revoke all the access and refresh tokens issued to that user. This will log the user out from everywhere. This really comes into help when the user changes his password using reset password or forget password option and you have to log the user out from everywhere.
You need to delete the token from the database table oauth_access_tokens
you can do that by creating a new model like OauthAccessToken
Run the command php artisan make:model OauthAccessToken to create the model.
Then create a relation between the User model and the new created OauthAccessToken Model , in User.php add :
public function AauthAcessToken(){
return $this->hasMany('\App\OauthAccessToken');
}
in UserController.php , create a new function for logout:
public function logoutApi()
{
if (Auth::check()) {
Auth::user()->AauthAcessToken()->delete();
}
}
In api.php router , create new route :
Route::post('logout','UserController#logoutApi');
Now you can logout by calling posting to URL /api/logout
This is sample code i'm used for log out
public function logout(Request $request)
{
$request->user()->token()->revoke();
return response()->json([
'message' => 'Successfully logged out'
]);
}
Create a route for logout:
$router->group(['middleware' => 'auth:api'], function () use ($router) {
Route::get('me/logout', 'UserController#logout');
});
Create a logout function in userController ( or as mentioned in your route)
public function logout() {
$accessToken = Auth::user()->token();
DB::table('oauth_refresh_tokens')
->where('access_token_id', $accessToken->id)
->update([
'revoked' => true
]);
$accessToken->revoke();
return response()->json(null, 204);
}
I am using Laravel 6.12.0, below function is working for me.
public function logout(Request $request){
$accessToken = Auth::user()->token();
$token= $request->user()->tokens->find($accessToken);
$token->revoke();
$response=array();
$response['status']=1;
$response['statuscode']=200;
$response['msg']="Successfully logout";
return response()->json($response)->header('Content-Type', 'application/json');
}
This is my first post.. and i find a clean solution (Laravel last Version)
/**
* Logout api
*
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
if (Auth::check()) {
$token = Auth::user()->token();
$token->revoke();
return $this->sendResponse(null, 'User is logout');
}
else{
return $this->sendError('Unauthorised.', ['error'=>'Unauthorised'] , Response::HTTP_UNAUTHORIZED);
}
}
Below is the simplest way I found to do it.
1. USE database SESSION INSTEAD OF file SESSION
Official documention
php artisan session:table
php artisan migrate
Replace SESSION_DRIVER=file by SESSION_DRIVER=database in your .env file.
2. DELETE USER SESSION RIGHT AFTER LOGIN
After a user is redirected to your frontend and logs in to finally get a token, you probably call a route in api/routes.php to get the user information, that's where I'm closing the user backend session before sending back user information to the frontend:
Route::middleware('auth:api')->get('/user', function (Request $request) {
// Close user session here
Illuminate\Support\Facades\DB::table('sessions')
->whereUserId($request->user()->id)
->delete();
return $request->user();
});
3. REVOKE TOKENS AT LOGOUT
Then, to "log out" (actually, revoke tokens) the user from the frontend, you just need to call another route to revoke the token and refresh_token:
Route::middleware('auth:api')->post('/logout', function (Request $request) {
// Revoke access token
// => Set oauth_access_tokens.revoked to TRUE (t)
$request->user()->token()->revoke();
// Revoke all of the token's refresh tokens
// => Set oauth_refresh_tokens.revoked to TRUE (t)
$refreshTokenRepository = app('Laravel\Passport\RefreshTokenRepository');
$refreshTokenRepository->revokeRefreshTokensByAccessTokenId($request->user()->token()->id);
return;
});
You may prefer to put these two closures in the UserController.
Hope help someone:
if (Auth::check()) {
$request->user()->tokens->each(function ($token, $key) {
$token->delete();
});
}
Good Luck.
I use this in my project to logout from multiple device.
public function logout(Request $request, $devices = FALSE)
{
$this->logoutMultiple(\Auth::user(), $devices);
return response()->json([], 204);
}
private function logoutMultiple(\App\Models\User $user, $devices = FALSE)
{
$accessTokens = $user->tokens();
if ($devices == 'all') {
} else if ($devices == 'other') {
$accessTokens->where('id', '!=', $user->token()->id);
} else {
$accessTokens->where('id', '=', $user->token()->id);
}
$accessTokens = $accessTokens->get();
foreach ($accessTokens as $accessToken) {
$refreshToken = \DB::table('oauth_refresh_tokens')
->where('access_token_id', $accessToken->id)
->update(['revoked' => TRUE]);
$accessToken->revoke();
}
}
Try this code to help you to logout from passport authentication.
Route::post('/logout', function(){
if (Auth::check()) {
Auth::user()->AauthAcessToken()->delete();
}
return response()->json([
'status' => 1,
'message' => 'User Logout',
], 200);
});
check whether your model contains OauthAccessToken which needs to connect with the database oauth_access_tokens. The access token is stored in the database table oauth_access_tokens. and makes a relation from users to oauth_access_tokens.
public function AauthAcessToken(){
return $this->hasMany(OauthAccessToken::class);
}
You can use following code to remove to token for logged in user.
$request->user()->token()->revoke();
If you want to learn about this in-depth then watch this tutorial:
https://www.youtube.com/watch?v=UKSQdg1uPbQ
public function logout(Request $request)
{
$request->user()->token()->revoke();
if ($request->everywhere) {
foreach ($request->user()->tokens()->whereRevoked(0)->get() as $token) {
$token->revoke();
}
}
return response()->json(['message' => 'success']);
}