Laravel - Trying to get property 'token' of non-object", exception: "ErrorException" - php

I am using Angular-7 as frontend and Laravel-5.8 as backend for a web application.
ApiController.php
public function login(Request $request)
{
$request->validate([
'email' => 'required|string|email',
'password' => 'required|string',
'remember_me' => 'boolean'
]);
$credentials = request(['email', 'password']);
$credentials['active'] = 1;
$credentials['deleted_at'] = null;
if(!Auth::attempt($credentials))
return response()->json([
'message' => 'Unauthorized'
], 401);
$user = $request->user();
$res = User::with('roles')->find($user->id);
$tokenResult = $user->createToken('MyApp')->accessToken;
$token = $tokenResult->token;
if ($request->remember_me)
$token->expires_at = Carbon::now()->addWeeks(13);
$token->save();
return response()->json([
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse($tokenResult->token->expires_at)->toDateTimeString(),
'user' => response()->json($res)->original
]);
}
From the Angular frontend, when I click on submit on the Login Page, it suppose to redirect to home page. But I got this error:
{message: "Trying to get property 'token' of non-object", exception: "ErrorException", file: "C:\xampp\htdocs\clientportal-app\backend\app\Http\Controllers\ApiController.php", line: 212, trace: Array(35)}
When I checked line 212 from Laravel ApiController from the code above, this is what I have:
$token = $tokenResult->token;
How do I resolve it?

Laravel Passport requires following configuration.
User model needs to use the HasApiTokens trait.
class User extends Authenticatable
{
use Notifiable, HasApiTokens;
}
Passport routes need to added to the boot() method of AuthServiceProvider
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
And finally change the api driver to passport in auth config file.
'api' => [
'driver' => 'passport',
'provider' => 'users',
]
You need to migrate Passport tables
php artisan migrate
and generate encryption keys
php artisan passport:install
Clear cache with
php artisan config:cache
and serve your app
php artisan serve

Related

Unauthenticated in Laravel JWT authentication

I used jwt-auth.
It works well in login, but when I try to register it and go through the login request the error below occurred.
"message": "Unauthenticated."
Here is the source code:
config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => True,
],
routes/api.php:
Route::group([
'middleware' => 'api',
'namespace' => 'App\Http\Controllers',//must include the path
'prefix' => 'auth'
], function ($router) {
Route::post('login', 'AuthController#login');
Route::post('signup', 'AuthController#signup');
Route::post('logout', 'AuthController#logout');
Route::post('refresh', 'AuthController#refresh');
Route::post('me', 'AuthController#me');
});
AuthController.php
public function __construct()
{
$this->middleware('auth:api', ['except' => ['login,signup']]);
}
public function login()
{
$credentials = request(['email', 'password']);
if (! $token = auth()->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
public function signup(Request $request){
$validation = $request->validate([
'email' =>'required',
'name' =>'required',
'password'=>'required|min:6|confirmed',
]);
$data = array();
$data['name'] = $request->name;
$data['email'] = $request->email;
$data['password'] = Hash::make($request->password);
DB::table('users')->insert($data);
return $this->login($request);
}
I provided DB and Hash classes. In postman, I put the route in the POST method and set headers Accept and content-type as application/json formate and in the body part, I set x-www-form and input all the keys and values with confirmation_password key. It not inserting into the database and showing the error message. I tried it by clearing the config cache and route cache. I also tried it with raw and json format.
i think you problem with ur constractor middleware u didn't make the except value right u have to make to different values for except like that
$this->middleware('auth:api', ['except' => ['login','signup']]);
Better use create or save Method to store the new user. After you store user in your database you can generate a usertoken and send him back. And the user is logged in. Every further request is then regulated via the token.
$token = // generate an new token with the JWT toker Helper method ;
return response()->json([
'status' => 'ok',
'token' => $token,
'user' => $user
], 201);

Laravel Passport API call always return Unauthenticated

So I have setup my API with Passport and tried to make GET request for almost a week now but still getting the response bellow :
{
"message": "Unauthenticated."
}
Below are my configuration :
Auth.php
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'token',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
//'hash' => true,
],
],
AuthServiceProvider.php
public function boot()
{
$this->registerPolicies();
//
Passport::routes();
Passport::tokensExpireIn(Carbon::now()->addDays(7));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(14));
}
RouteServiceProvider
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('auth:api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
Controller : Token request function using user credentials as per laravel doc
public function callback(Request $request)
{
$http = new Client();
$token_url=url('oauth/token');
$response = $http->post($token_url, [
'form_params' => [
'grant_type' => 'password',
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'username'=>'my-username',
'password'=>'my-password',
'scope' =>'*',
],
]);
return json_decode((string) $response->getBody(), true);
}
Which returns an access_token that I use in my request in my request . I tried all the solution listed below and none of them worked :
.htaccess
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Passport.php line 167
public static function tokensExpireIn(DateTimeInterface $date = null)
{
if (is_null($date)) {
return static::$tokensExpireAt
? Carbon::now()->diff(static::$tokensExpireAt)
: new DateInterval('P1Y');
}
static::$tokensExpireAt = $date;
return new static;
}
Please help , I'm desperate now :)
The problem is how you authenticate and which token you are using.
There are 2 ways to generate token
Users login and you use create token to get the token if user is authenticated.
Generate a client and use PRE built routes by passport to get token
Now in the API routes you have to tell in your method how you are authenticating for example
// Below one is for authenticating Client token
Route::get('/test', 'Api\TestController#index')->middleware('client_credentials');
// Below one is for the User token
Route::get('/test', 'Api\TestController#index')->middleware('auth:api');
And Remember if you are using client authentication, you have to add the below line in routemiddleware in App/http/kernel.php
'client_credentials' => \Laravel\Passport\Http\Middleware\CheckClientCredentials::class
I hope that solves issues
Try creating a new password grant client with:
php artisan passport:client --password
You'll get an output like:
What should we name the password grant client? [Laravel Password Grant Client]:
>
Password grant client created successfully.
Client ID: 4
Client secret: WlRYEbA5lt5esbi0MuFyJPzPDmHDGsk3iC5QGw7d
Use those credentials to fill your client id and secret. Standard client credentials created through the Vue component interface do not work for password grants.

laravel and jwt: always return Unauthorized

I want to use JWT to login in my API but it always give me
error: "Unauthorized".
Before this, i already register the email and password of the user in my database before trying to login
here's my code :
class UserController extends Controller
{
public function __construct()
{
$this->middleware('auth:api', ['except' => 'login']);
}
public function login(Request $request) {
$validator = Validator::make($request->all(), [
'email' => 'required|email|max:255',
'password' => 'required|string|min:6|max:255',
]);
if($validator->fails()) {
return response()->json([
'status' => 'error',
'messages' => $validator->messages()
], 200);
}
if (! $token = auth()->attempt(['email' => $request->email, 'password' => $request->password])) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
protected function respondWithToken($token) {
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => Auth::guard()->factory()->getTTL() * 60
]);
}
/**
* Get the guard to be used during authentication.
*
* #return \Illuminate\Contracts\Auth\Guard
*/
public function guard()
{
return Auth::guard('api');
}
here's my guard and default in config/auth.php :
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
here's my frontend using VueJs that does the login :
axios.post('http://localhost:8000/api/login', loginData)
.then(response => {
console.log(response)
})
.catch(error => {
commit('loginStop', error.response.data.error);
commit('updateAccessToken', null);
console.log(error.response);
})
here's my web.php :
Route::group(['prefix' => 'api'], function() {
Route::post('/register', 'UserController#register');
Route::post('/login', 'UserController#login');
});
Here's my output of php artisan route:list :
Based on the comments, you aren't hashing the password of the user that you inserted in the database.
But you have to do it as Auth::attempt checks if the provided password would match the hash stored in the database.
If you still want to register the user manually, you can hook up a tinker interactive shell with php artisan tinker command and then user Hash::make('yourpassword') to generate an hashed password using the setted Laravel's password hashing system (defaults to bcrypt).
Then you just have to copy the output string into your database. The login should finally work as the Auth guard now can check the user input agains a correct database user with a proper hashed password.
I had a totally different issue.
The auth()->attempt method was not comparing the password to my User model password for some reason.
After adding the following to my User model:
public function getAuthPassword() {
return $this->password;
}
Everything worked like a charm
The same problem to me, I solved by:
Use tinker to generate user credentials, email and password
content type in Headers: application/x-www-form-urlencoded

Laravel Passport - Invalid credentials using grant_type is passowrd

I am having difficulty setting up Passport in Laravel 5.6. The first time when I followed this tutorial, I had implemented perfectly but now again when I am following than getting following error.
{
"error": "invalid_credentials",
"message": "The user credentials were incorrect."
}
I have tried out all possible solutions but none of them works. So thought to post it here.
Info:
I am using iMac - High Sierra. storage directory has 777
permission. I have set using sudo chmod -R 777 storage command.
However, when I checked the laravel.log file didn't have permission so
I have grant 777 to it as well. still getting the error.
Laravel error log - laravel.log
local.ERROR: The user credentials were incorrect. {"exception":"[object] (League\\OAuth2\\Server\\Exception\\OAuthServerException(code: 6): The user credentials were incorrect. at /Users/username/Sites/mysite/vendor/league/oauth2-server/src/Exception/OAuthServerException.php:160)
My Implementation Steps
I run composer require laravel/passport
Added passport service provider in app.php Laravel\Passport\PassportServiceProvider::class,
Migrated the database php artisan migrate
Added Passport::routes()
Added use HasApiTokens to User model
In auth.php set gourds api driver to password
Passport client credentials php artisan passport:client --passoword
Passport keys php artisan passport:keys
Added route and register controller as below
Route
Route::post( 'register', 'Api\Auth\RegisterController#register' );
RegisterController Class
namespace App\Http\Controllers\Api\Auth;
use App\User;
use function bcrypt;
use function dd;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Route;
use Laravel\Passport\Client;
use function response;
class RegisterController extends Controller
{
private $client;
public function __construct() {
$this->client = Client::findOrFail(1);
}
public function register( Request $request ) {
$this->validate( $request, [
'name' => 'required',
'email' => 'required|email|unique:users,email',
'password' => 'required|min:6|confirmed',
] );
$user = User::create( [
'name' => request( 'name' ),
'email' => request( 'email' ),
'password' => bcrypt( 'password' )
] );
$params = [
'grant_type' => 'password',
'client_id' => $this->client->id,
'client_secret' => $this->client->secret,
'username' => request( 'email' ),
'password' => request( 'password' ),
'scope' => '*'
];
$request->request->add( $params );
$proxy = Request::create( 'oauth/token', 'POST' );
return Route::dispatch( $proxy );
}
}
You are hashing the word 'password' not the actual password coming from request.
You should use it like this:
bcrypt(request('password'))
try to use hash::make function instead of bcrypt for your password when creating user like below
$user = User::create([
'name' => request('name'),
'email' => request('email'),
'password' => Hash::make(request('password'))
]);

How to use token authentication in laravel web page

I am trying to use JWT for laravel web page instead of session. so I made some changes.
Installed jwt-auth and configure
Then changed default guard as api in config/auth.php
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
...
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
Now I am getting error
(1/1) FatalErrorException Call to undefined method
Illuminate\Auth\TokenGuard::attempt() in AuthenticatesUsers.php (line
75)
How to fix this and start token authentication for laravel web page(blades not API).
I'm also using jwt protecting our api. You should change your config like below:
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
...
'api' => [
'driver' => 'jwt', // KEY POINT!!!
'provider' => 'users',
],
],
Make sure the jwt library installed correctly:
Tymon\JWTAuth\Providers\LaravelServiceProvider::class is added in your config/app.php.
Your user model implements JWTSubject interface if you use eloquent model in your provider.
I found the solution here : https://github.com/tymondesigns/jwt-auth/issues/860
In /routes/api.php - added a few basic authentication routes
Route::post('login', 'Auth\LoginController#login');
Route::get('/user', function (Request $request) {
$user = $request->user();
return dd($user);
})->middleware('auth:api');
In /app/http/Controller/auth/LoginController.php
and then override methods in login contoller
public function login(Request $request)
{
$credentials = $request->only(["email","password"]);
if ($token = $this->guard()->attempt($credentials)) {
return $this->sendLoginResponse($request, $token);
}
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
protected function sendLoginResponse(Request $request, $token)
{
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user(), $token);
}
protected function authenticated(Request $request, $user, $token)
{
setcookie("jwt_token", $token);
return redirect('/');
return response()->json([
'token' => $token,
]);
}
protected function sendFailedLoginResponse(Request $request)
{
return response()->json([
'message' => "not found",
], 401);
}
Adding middleware AddToken
public function handle($request, Closure $next)
{
$token = isset($_COOKIE["jwt_token"])?$_COOKIE["jwt_token"]:"";
//$request['token'] = $token;//this is working
$request->headers->set("Authorization", "Bearer $token");//this is working
$response = $next($request);
//$response->header('header name', 'header value');
return $response;
}
Register middleware in Kernel.php
protected $middleware = [
....
\App\Http\Middleware\AddToken::class,
];
I think you can try this :
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
EDIT
You can find some help from the step by step example. In this example you need to focus on how to configure and use that token base authentication.
Hope this help you well.
Please refer this link. If you are using api as default then laravel authentication will throw an error.
Laravel uses default Session based authentication out of the box with the default scaffolding users-view-controller that you already have. You have additional means of adding your own custom guard in the doc, so you can make use of the guard as needed.
Therefore as #KevinPatel suggested, revert back to the default configuration, then in your route: group the route you want to be under JWT authentication, add the JWTMiddleware, in this case you have to update the controller responsible for your authentication to use the JWTAuth instead of the default auth.
You should check this answer if you need to understand it better check this answer on Laracasts
One recommended way to incorporate the JWTAuth is to go for Dingo API (of course you are not building api, but) because Dingo already added some flesh to the authentication and other routes management - so things are pretty easy to use and configure

Categories