When I used the passport package , I encountered this error
Call to a member function createToken() on null
Why do I get this error?
This is my code :
$users = Users::where('Email' , $username)
->where( 'Password' , $password)
->where('UserStatus' , config('global.active'))
->first();
if($users) {
$success['token'] = $users->createToken('MyApp')->accessToken;
return response()->json(['success' => $success], $this->successStatus);
} else {
return response()->json(['error'=>'Unauthorised'], 401);
}
$user = Auth::user(); is unnecessary and is what is causing your error.
$user = Users::where('Email' , $username)->where( 'Password' , $password)->where('UserStatus' , config('global.active'))->first();
if($user){
$success['token'] = $user->createToken('MyApp')->accessToken;
return response()->json(['success' => $success], $this->successStatus);
}else{
return response()->json(['error'=>'Unauthorised'], 401);
}
If $users were null, there's no way that part of the control structure where createToken is getting called would be reached. I wonder if this is a red herring, and there's some middleware at work here. There are actually three instances of a method by that same name, and the namespace in your error message is notable absent there:
/vendor/laravel/framework/src/Illuminate/Auth/Passwords/PasswordBroker.php
/vendor/laravel/passport/src/ApiTokenCookieFactory.php
/vendor/laravel/passport/src/HasApiTokens.php
That last one is a trait being used by the User model, and is the one you're calling. But I'm wondering if that error is actually coming from one of the other two. Check your error-log, probably in /storage/logs/laravel.log, and see if there's a stack-trace that might lend a clue.
You can do other way around to make it work.
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
public function authenticate(Request $request)
{
// add UserStatus logic here if any
if(Auth::attempt(['Email' => $request->username, 'Password' => $request->password], $request->remember))
{
$user = Auth::user();
$success['token'] = $request->user()->createToken('MyApp')->accessToken;
return response()->json(['success' => $success], $this->successStatus);
}
return response()->json(['error'=>'Unauthorised'], 401);
}
Related
I want that users can login with the registration number assigned to them or email. I have working api which only login users with email
public $successStatus = 200;
public function login(){
if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){
$user = Auth::user();
$success['token'] = $user->createToken('MyApp')-> accessToken;
return response()->json(['success' => $success], $this-> successStatus);
}
else{
return response()->json(['error'=>'Unauthorised'], 401);
}
}
You can check the value of the email in your request parameter to determine if an email or number has been provided and then attempt to log in your user that way.
public function login()
{
// determine if the value of the `email` field in the request
// is a valid `email` or not
$identity = filter_var(request('email'), FILTER_VALIDATE_EMAIL) ? 'email' : 'number';
// use the value of $identity for specifying the field,
// to compare against the value of the `email` in the request
if (Auth::attempt([$identity => request('email'), 'password' => request('password']))) {
$success['token'] = $user->createToken('MyApp')-> accessToken;
return response()->json(['success' => $success], $this-> successStatus);
}
return response()->json(['error'=>'Unauthorised'], 401);
}
This is my code in LoginController:
public function handleProviderCallback($provider)
{
$socialUser = Socialite::driver($provider)->stateless()->user();
$user = User::where('email', $socialUser->getEmail())->first();
if (!$user) {
$user = User::create([
'name' => $socialUser->getName(),
'email' => $socialUser->getEmail(),
'password' => Hash::make('12345678'),
'social_id' => $socialUser->getId(),
]);
}
Auth::login($user, true);
return redirect()->intended($this->redirectPath());
}
When performing normal login, it redirects to intended. But, in case of social login, it doesn't. What could be the cause?
I had a similar problem. You have to store the path you want to redirect in a session and then redirect the the path intended. I am also using the Socialite. Here is how I solved it.
public function redirect($provider)
{
session()->put('intended_url', url()->previous());
return Socialite::driver($provider)->redirect();
}
public function callback(Request $request, $provider){
$intendedUrl = session('intended_url');
if (!$request->has('code') || $request->has('denied')) {
return redirect('/');
}
$userSocial = Socialite::driver($provider)->stateless()->user();
$users = User::where(['email' => $userSocial->getEmail()])->first();
if($users){
Auth::login($users);
return redirect()->intended($intendedUrl);
}else{
$user = User::create([
'name' => $userSocial->getName(),
'email' => $userSocial->getEmail(),
'provider_id' => $userSocial->getId(),
'provider' => $provider,
]);
Auth::login($user);
return redirect()->intended($intendedUrl);
}
}
Before the redirect I store the previous route and then I use it. So no matter from which URL the user signs in, it will be redirected to the same page.
Check your url()->previous() in my case I actually needed the current url. So I used session()->put('intended_url', url()->full()); in the controller I hit and after lgoin redirect to this url as in the example.
Also you need to use Session::forget('intended_url'); afeter assigning it to variable.
i am getting error, Internal server error,
GET http://isp.local/teachers/168/edit 500 (Internal Server Error)
Controller:
public function edit($id)
{
$teacher = DB::table('teachers')
->find($id)
->select('*')
->first();
return response()->json([
'status' => 'success',
'teacher' => $teacher,
]);
}
while when i make following changes in controller i am getting correct results, what is issue in above code?
Controller:
public function edit($id)
{
$teacher = Teacher::find($id);
return response()->json([
'status' => 'success',
'teacher' => $teacher,
]);
}
That query is wrong. ->find() executes the query, as does ->first(), and everything is selected by default, so ->select('*') is unnecessary.
$teacher = DB::table('teachers')->find($id);
Should be enough. But you're already using the correct
$teacher = Teacher::find($id);
So there isn't much point to using the DB::table() approach.
Try
->whereId($id)
or
where('id',$id)
I added API authentication to my Laravel app using passport. I followed this tutorial:
https://medium.com/techcompose/create-rest-api-in-laravel-with-authentication-using-passport-133a1678a876
Now how do I redirect to a view after the user is been authenticated? I need this to embed my webapp to another portal using single sign on.
This returns the user values:
public function details()
{
$user = Auth::user();
return response()->json(['success' => $user], $this->successStatus);
}
This tells me the user is unauthorized:
public function details()
{
$user = Auth::user();
return redirect('/home');
}
This is my route:
Route::post('details', 'API\UserController#details')->middleware('auth:api');
This is my login:
public function login(){
if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){
$user = Auth::user();
$success['token'] = $user->createToken('MyApp')->accessToken;
return response()->json(['success' => $success], $this-> successStatus);
}
else{
return response()->json(['error'=>'Unauthorised'], 401);
}
}
You can validate user after
Auth::attempt(['email' => request('email'), 'password' => request('password')])
if(Auth::check())
return redirect()->route('<route_name>');
When a user logs in I want them to be redirected to their profile page instead of homepage. I have a method in another controller that gets a user profile. Not sure what I need to do since the user profile takes a username variable but when user logs in I'm only asking for email and password.
My route file, but the following method is in a different controller from the authentication controller.
Route::get('/user/{username}', [
'uses' => 'ProfileController#getProfile',
'as' => 'profile.index',
'middleware' => ['auth'],
]);
My following method is in my authentication controller.
public function postSignin(Request $request)
{
$this->validate($request, [
'email' => 'required',
'password' => 'required',
]);
if (!Auth::attempt($request->only(['email', 'password']), $request->has('remember'))) {
return redirect()->back()->with('info' , 'Could not sign you in with that info.');
}
$user= User::where('username', $username)->first();
return redirect()->route('profile.index')
->with('info', 'You are now signed in.')
->with('user', $user);
}
The following is in my profile controller..
public function getProfile($username)
{
$user= User::where('username', $username)->first();
if (!$user){
abort(404);
}
return view('profile.index')
->with('user', $user);
}
To correctly build the route, you need to pass the username here:
$user = User::where('username', $username)->first();
return redirect()->route('profile.index', ['username' => $user->username])
->with('info', 'You are now signed in.')
->with('user', $user);
Get the username from the email provided and pass the $username variable to route:
public function postSignin(Request $request)
{
if (!Auth::attempt($request->only(['email', 'password']),$request->has('remember')))
{
return redirect()->back()->with('info' , 'Could not sign you in with that info.');
}
$username=User::where(['email'=>$request->email])->first()->username;
return redirect()->route('profile.index')->with('username', $username);
}
You can use as like below.
if (!Auth::attempt($request->only(['email', 'password']), $request->has('remember'))) {
return redirect('profile.index')->with('info' , 'Could not sign you in with that info.');