I am new in Laravel and using JWT auth in laravel 5.5.18 but its not working for me its give error in api login
Interface 'Tymon\JWTAuth\Contracts\JWTSubject' not found"
Can any one help me how to fix it.
Thanks
Updated Article and Source Code - www.ultimateakash.com
composer remove tymon/jwt-auth
composer dump-autoload
then install
composer require tymon/jwt-auth:dev-develop --prefer-source
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
php artisan jwt:secret
Route::post('login', 'ApiController#login');
Route::post('register', 'ApiController#register');
Route::group(['middleware' => 'auth.jwt'], function () {
Route::get('logout', 'ApiController#logout');
Route::get('user', 'ApiController#getAuthUser');
});
?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* 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',
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
class ApiController extends Controller
{
public function register(Request $request)
{
$user = new User;
$user->name = $request->name;
$user->email = $request->email;
$user->password = bcrypt($request->password);
$user->save();
return response()->json([
'success' => true,
'data' => $user
], 200);
}
public function login(Request $request)
{
$input = $request->only('email', 'password');
$jwt_token = null;
if (!$jwt_token = JWTAuth::attempt($input)) {
return response()->json([
'success' => false,
'message' => 'Invalid Email or Password',
], 401);
}
return response()->json([
'success' => true,
'token' => $jwt_token,
]);
}
public function logout(Request $request)
{
$this->validate($request, [
'token' => 'required'
]);
try {
JWTAuth::invalidate($request->token);
return response()->json([
'success' => true,
'message' => 'User logged out successfully'
]);
} catch (JWTException $exception) {
return response()->json([
'success' => false,
'message' => 'Sorry, the user cannot be logged out'
], 500);
}
}
public function getAuthUser(Request $request)
{
$this->validate($request, [
'token' => 'required'
]);
$user = JWTAuth::authenticate($request->token);
return response()->json(['user' => $user]);
}
}
You may considerate to use Laravel Passport
From the laravel official docs: https://laravel.com/docs/5.8/passport
Laravel makes API authentication a breeze using Laravel Passport, which provides a full OAuth2 server implementation for your Laravel application in a matter of minutes. Passport is built on top of the League OAuth2 server that is maintained by Andy Millington and Simon Hamp.
Indeed since the library is maintained by the creator of Laravel, it will be more up-to-date and stable for Laravel than other concurrent libraries.
Related
I am working on a project (web and api) and using Laravel sanctum in my project, I am trying to make an api get request on postman to see user information after logged in but I keep getting this "message": "Unauthenticated." error but I notice that when I was using the get to access user information from my api on localhost (http://127.0.0.1:8000/) it was showing the details and working fine, but when I test it with my domain url (http://sotun.com/mark/live) show Unauthenticated.
My Controller
class AuthApiController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
'device_name' => 'required',
]);
$user = User::where('email', $request->email)->first();
if (! $user || ! Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}
$token = $user->createToken($request->device_name)->plainTextToken;
$response = [
'user' => $user,
'token' => $token,
];
return response ($response, 201);
}
public function user(Request $request)
{
return $request->user();
}
}
api.php
use App\Http\Controllers\AuthApiController;
Route::group(['middleware' => ['auth:sanctum']], function() {
Route::get('/user', [AuthApiController::class, 'user']);
Route::post('/logout', [AuthApiController::class, 'logout']);
});
User Model
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable implements MustVerifyEmail
{
use HasApiTokens, HasFactory, Notifiable;
protected $fillable = [
'name',
'email',
'password',
'user_id',
'user_type',
'user_job',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
}
In the .env I added the below
.env
SANCTUM_STATEFUL_DOMAIN=http://sotun.com/mark/live
SESSION_DOMAIN=http://sotun.com/mark/live
postman output
But the same result, please I will help to solve this Thanks
Modify your .env file configurations to:
SANCTUM_STATEFUL_DOMAINS="sotun.com,127.0.0.1:8000"
SESSION_DOMAIN=sotun.com
Notice the pluralization of the environmental variable SANCTUM_STATEFUL_DOMAINS.
So guys,
I have an app that needs to login.
After login and getting the API and token, it has to redirect to a dashboard, but unfortunately, I can't make it to a dashboard view.
I try to find answers on the forum but can't find one that suits my code.
Here is my api.php
Route::post('/login', App\Http\Controllers\api\LoginController::class)->name('login');
my web.php
Route::get('/dashboard', [Controller::class, 'dashboard']);
my LoginController
class LoginController extends Controller
{
/**
* Handle the incoming request.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function __invoke(Request $request)
{
//set validation
$validator = Validator::make($request->all(), [
'email' => 'required',
'password' => 'required'
]);
//if validation fails
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
//get credentials from request
$credentials = $request->only('email', 'password');
//if auth failed
if(!$token = auth()->guard('api')->attempt($credentials)) {
return response()->json([
'success' => false,
'message' => 'Email atau Password Anda salah'
], 401);
}
//if auth success
return response()->json([
'success' => true,
'user' => auth()->guard('api')->user(),
'token' => $token
], 200);
}
my AuthController :
class AuthController extends Controller
{
public function login(Request $request){
$email = $request->input("email");
$password = $request->input("password");
$request = Request::create('http://localhost:8000/api/login', 'POST',[
'name'=>$email,
'password'=>$password,
]);
$response = json_decode(Route::dispatch($request)->getContent());
// echo($response->success);
if($response->success == 1 || true){
return redirect()->route('dashboard',["response"=>$response]);
}else{
return redirect()->back();
}
}
}
Controller.php where dashboard route is defined:
public function dashboard()
{
return view('dashboard', [
"title" => "Dashboard",
]);
}
if I'm using this code, the error I get is:
Route [dashboard] not defined.
but if I'm not using return redirect and use return view instead. I can go to my dashboard, but the URL is localhost:8000\auth\login which is not what I want.
is there any suggestion so I can get my view on Dashboard?
Thank you very much.
I have used JWT in Laravel for user Authentication
Auth Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
use Illuminate\Auth\Events\Verified;
use Validator;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
class AuthController extends Controller
{
public function __construct() {
$this->middleware('auth:api', ['except' => ['login', 'register']]);
}
/**
* Get a JWT via given credentials.
*
* #return \Illuminate\Http\JsonResponse
*/
public function login(Request $request){
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required|string|min:6',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
if (! $token = auth()->attempt($validator->validated())) {
return response()->json(['status'=>true,'error_message' => 'Invalid Credentials'], 401);
}
return $this->createNewToken($token);
}
/**
* Register a User.
*
* #return \Illuminate\Http\JsonResponse
*/
public function register(Request $request) {
$messages = [
'password.confirmed' => 'Password Confirmation should match the Password',
'password.min' => ' Password should be minimum 6 digits',
];
$validator = Validator::make($request->all(), [
'name' => 'required|string|between:2,100',
'email' => 'required|string|email|max:100|unique:users',
'password' => 'required|string|confirmed|min:6',
],$messages);
if($validator->fails()){
return response()->json($validator->errors(), 422);
}
$user = User::create(array_merge(
$validator->validated(),
['password' => bcrypt($request->password)]
));
return response()->json([
'message' => 'Successfully registered',
], 201);
}
/**
* Log the user out (Invalidate the token).
*
* #return \Illuminate\Http\JsonResponse
*/
public function logout() {
auth()->logout();
return response()->json(['message' => 'User successfully signed out']);
}
/**
* Refresh a token.
*
* #return \Illuminate\Http\JsonResponse
*/
public function refresh() {
return $this->createNewToken(auth()->refresh());
}
/**
* Get the authenticated User.
*
* #return \Illuminate\Http\JsonResponse
*/
public function userProfile() {
return response()->json(auth()->user());
}
/**
* Get the token array structure.
*
* #param string $token
*
* #return \Illuminate\Http\JsonResponse
*/
protected function createNewToken($token){
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth()->factory()->getTTL() * 60,
'user' => auth()->user()
]);
}
}
routes :
Route::group([
'middleware' => ['api'],
'prefix' => 'auth'
], function ($router) {
Route::post('/login', [AuthController::class, 'login']);
Route::post('/register', [AuthController::class, 'register']);
Route::post('/logout', [AuthController::class, 'logout']);
Route::post('/refresh', [AuthController::class, 'refresh']);
Route::get('/user-profile', [AuthController::class, 'userProfile']);
Login and register is working
but when i access user-profile route getting this error :
Symfony\Component\Routing\Exception\RouteNotFoundException: Route
[login] not defined. in file
C:\wamp64\www\project\vendor\laravel\framework\src\Illuminate\Routing\UrlGenerator.php
on line 420
and i cannot get id of user if some user is logged in using : auth()->user()->id
auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => false,
],
'admin' => [
'driver' => 'session',
'provider' => 'users',
],
],
Model :
<?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 Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{ #HasFactory,
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
'email',
'password',
'otp',
'user_verification_token',
'verified',
'token',
'email_verified_at'
];
/**
* 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',
];
public function getJWTIdentifier() {
return $this->getKey();
}
public function getJWTCustomClaims() {
return [];
}
}
Any suggestion is highly appreciated
Thanks
Error message says there is no route that named as 'login'
Route::post('/login', [AuthController::class, 'login'])->name('login');
I am making a custom login in Laravel 7. Register is done correctly but login is not working properly. What can i do for login using custom table user_master.
My database table is user_masters.
User_master model:
<?php
namespace App;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User_master extends Model implements Authenticatable
{
//
use HasApiTokens, Notifiable;
protected $fillable = [
'user_full_name', 'user_email', 'user_password','user_otp_code','user_phone'
];
protected $hidden = [
'user_password'
];
protected $casts = [
'email_verified_at' => 'datetime',
];
}
This my controller. what have I done wrong here?
<?php
// namespace App\Http\Controllers;
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\User_master;
use Illuminate\Support\Facades\Auth;
use Validator;
use Illuminate\Http\Request;
class UserMasterController extends Controller
{
//
public $successStatus = 200;
/**
* login api
*
* #return \Illuminate\Http\Response
*/
public function login(){
if(Auth::attempt(['user_full_name' => request('user_full_name')])){
$user = Auth::user_master();
$success['token'] = $user->createToken('MyApp')-> accessToken;
return response()->json(['success' => $success], $this-> successStatus);
}
else{
return response()->json(['error'=>'Unauthorised'], 401);
}
}
/**
* Register api
*
* #return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'user_full_name' => 'required',
'user_email' => 'required|email',
'user_password' => 'required',
'c_password' => 'required|same:user_password',
]);
if ($validator->fails()) {
return response()->json(['error'=>$validator->errors()], 401);
}
$input = $request->all();
$input['user_password'] = bcrypt($input['user_password']);
$user = user_master::create($input);
$success['token'] = $user->createToken('MyApp')-> accessToken;
$success['user_full_name'] = $user->user_full_name;
return response()->json(['success'=>$success], $this-> successStatus);
}
}
You need to set your authentication driver properly to work with your custom user Model.
Make these configuration in config/auth.php file ,in providers section:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User_master::class, // <---- Your custom user model
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
Notice:
You must implement Illuminate\Contracts\Auth\Authenticatable interface.
Illuminate\Foundation\Auth\User is a class, you cannot implement it.
I am using laravel 5.4 and Auth::login($user) is showing Type error:
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must
implement interface Illuminate\Contracts\Auth\Authenticatable,
instance of Illuminate\Database\Eloquent\Builder given, called in
/home/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php on
line 294
My User.php file is:
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'role', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
My AuthController.php is:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Auth;
use Illuminate\Support\Facades\Input;
use \Hash;
class AuthController extends Controller
{
//
public function register(Request $request){
$this->validate($request, [
'name' => 'required|max:30',
'email' => 'required|email|unique:users',
'regpassword' => 'required|alpha_num|confirmed'
]);
/*$user = new User();
$user['name'] = $request['name'];
$user['email'] = $request['email'];
$user['password'] = bcrypt($request['password']);
$user['role'] = 'user';
$user->save();
*/
$user = User::create(array(
'email' => Input::get('email'),
'name' => Input::get('name'),
'password' => Hash::make(Input::get('password')),
'role' => 'user'));
return 'success';
}
public function userLogin(Request $request){
$this->validate($request,[
'email' => 'required|email',
'password' => 'required'
]);
$user = User::where('email', '=', $request['email'])-> where('password' ,'=', Hash::make($request['password']))->where('role','=','user');
if($user){
Auth::login($user);
return $next($request);
}
else{
return redirect()->back();
}
}
}
My web.php
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController#index');
Route::post('/register', 'AuthController#register');
Route::post('/UserLogin','AuthController#userLogin');
Your problem is this:
$user = User::where('email', '=', $request['email'])-> where('password' ,'=', Hash::make($request['password']))->where('role','=','user');
Is lacking a call to get the result set back from the query. Add ->first().
What it' saying is:
You gave me an instance of the query Builder
But
I wanted a model that extends the authenticatable class
If you open App\User, you'll see that it does indeed extend this class:
class User extends Authenticatable {
This:
$user = User::where('email', '=', $request['email'])-> where('password' ,'=', Hash::make($request['password']))->where('role','=','user');
is not the way you will get the user.
Instead of
$user = User::where('email', '=', $request['email'])-> where('password' ,'=', Hash::make($request['password']))->where('role','=','user');
if($user){
Auth::login($user);
return $next($request);
}
else{
return redirect()->back();
}
you could use:
$logged = auth()->attempt(
['email' => $request['email'],
'password' => $request['password'],
'role' => 'user']);
if($logged) {
return $next($request); // probably it won't work. This is fine in middleware but not in controller
}
else{
return redirect()->back();
}
Solved my problem as following:
$user = User::where('email', '=' $request['email'])->where('role','=','user')->first();
if(Hash::check($request['password'],$user->password)){
Auth::login($user);
return 'success';
}