Laravel Passport : Users only have one token not many - php

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.

Related

Laravel Http request to route sends forever

I want to have a link in an email that send to the user, the link is the url of the site and has an api token for the user to authenticate with.
however I am trying to send an api request to get the user details so I can authenticate the user and redirect them to the relavent page, however doing this I end up with a request the spins endlessly.
what could be the issue and if there are any other solutions please let me know.
the link/request looks like this
http://localhost:8005/api/token?_token=<API TOKEN>
The controller that handles the request
<?php
namespace App\Http\Controllers;
use Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Http;
class PassportController extends Controller
{
function getToken(Request $request)
{
// return $request->_token;
return $user = Http::withToken($request->_token)->get('http://localhost:8005/api/user');
Auth::login($user);
return redirect('/dashboard');
}
}
Also when I send the request it gets stuck and I have to restart my php artisan serve again to make more requests, and every time i do so, It opens up on a new port, 8001,8002,8003 etc
You can make a call back to the app itself like this:
$tokenRequest = Request::create('/api/user', 'GET', ['name' => 'value']);
$tokenResult = app()->handle($tokenRequest);
Update the variables to match your implementations.

How to use refresh token in codeigniter rest api?

I'm new in codeigniter 4 rest api and oath. I'm able to create login that return the token and the refresh token. My problem is when the token has expired. How can I get new token using the refresh token? Do I have to create a new function in the controller for that? Or can it be the same endpoint as the login? I've read in some articles that I need to send grant_type, client_id, client_secret and the refresh token as a post. But I don't know the endpoint on where to send this. I'm totally new to this, please help me. Thanks.
User.php(Controller)
<?php namespace App\Controllers;
use \App\Libraries\Oauth;
use \OAuth2\Request;
use CodeIgniter\API\ResponseTrait;
use App\Models\UserModel;
class User extends BaseController
{
use ResponseTrait;
public function login(){
$oauth = new Oauth();
$request = new Request();
$respond = $oauth->server->handleTokenRequest($request->createFromGlobals());
$code = $respond->getStatusCode();
$body = $respond->getResponseBody();
return $this->respond(json_decode($body), $code);
}
Oauth.php
<?php namespace App\Libraries;
//use \OAuth2\Storage\Pdo;
use \App\Libraries\CustomOauthStorage;
class Oauth{
var $server;
function __construct(){
$this->init();
}
public function init(){
$dsn = getenv('database.default.DSN');
$username = getenv('database.default.username');
$password = getenv('database.default.password');
$storage = new CustomOauthStorage(['dsn' => $dsn, 'username' => $username, 'password' => $password]);
$this->server = new \OAuth2\Server($storage);
$this->server->addGrantType(new \OAuth2\GrantType\UserCredentials($storage));
}
}
When you want to implement an OAuth2 system with CI4, you're free to making it however you want since nothing is already created to do so in the framework. Here it looks like you're using bshaffer oauth2 lib for PHP (try to read their cookbook. It personally helped me a lot implementing it in a CI4 project : https://bshaffer.github.io/oauth2-server-php-docs/cookbook).
First if you want to make a refresh token with this lib you have to add the refreshtoken grant type to your server.
$this->server->addGrantType(new \OAuth2\GrantType\UserCredentials($storage));
// this add the refresh token grant type.
// param 'always_issue_new_refresh_token' allows you to catch a new refresh token
// when making a call with a refresh token
$this->server->addGrantType(new \OAuth2\GrantType\RefreshToken($storage, [
'always_issue_new_refresh_token' => true
]));
Then the lib will handle it for you with $respond = $oauth->server->handleTokenRequest($request->createFromGlobals());. You don't need to add anything in your controller.
It's up to you to create a new route in your Config/Routes.php for the refresh token call. But as your controller code will be the exact same it could be a good point to keep it on the same route.
Also the HTTP request you will send to your oauth server must have :
Header Content-Type as application/x-www-form-urlencoded
A body parameter grant_type=refresh_token. That's how your lib will determine that it needs to use the refresh token process.
An other parameter named refresh_token with the actual refresh token
Don't forget to read the lib's documentation which is pretty small but really clean : https://bshaffer.github.io/oauth2-server-php-docs/grant-types/refresh-token/

Auth::check() returning false in Laravel 5.4

I am using laravel 5.4 as backend for my application and for front-end I am using angular. I am using laravel auth for authentication.
Issue is Auth::attempt() is working fine and if immediately I print the Auth::user() then it prints the data but it returns false if I try to fetch it in next method. But this functionality is working fine in hosted server.
Tested,
Changing session from file to database.
Changes in kernel.php (Content of $middleware).
Did php artisan make:auth one more time.
Did changes in user table column.
Adding private $primarykey = 'id' to model.
Adding 'web' middleware to all routes.
This is my Controller
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Input;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\User;
public function login()
{
if (Auth::attempt(['email' => $email, 'password' => $password ]))
{
$response = array('response' =>'Succssfully Login!' , 'success' => true);
return $response;
}
}
This is where i am using Auth::check() in the same controller
public function check()
{
if(Auth::check())
$response = array('response' =>'Authenticated' , 'success'=>true);
else
$response = array('response' =>'UnAuthenticated' , 'success'=>false);
return $response;
}
I am confused because same code is working fine in hosted server but not working on localhost. Do I need to do any http related changes in laravel for this?
In case your Angular application is outside laravel, and loading without using blade template to load your Angular app's entry point i.e. Angular's index.html then what happens is Laravel is not able to set session for the app, hence when you request for the next time your laravel is not able to recognise the session so it gives false when you call Auth::check().
To achieve authentication on external (i.e Angular app on your case) you should use either Laravel Passport's password client or JWT based authentication using https://github.com/tymondesigns/jwt-auth <- this package. (Instructions on the package's readme file)
For angular and web based app I would prefer to go with JWT.

How To Save PassportToken on user login laravel

i make API by laravel passport
i wanna save passport token in cookies when login is successful
i tried to make this in home controller but it always generate different key
Have you tried withCookie method of a Response object?
use Illuminate\Http\Response;
...
$UserToken = Auth::user()->createToken('MyApp')->accessToken;
$view = view('Ades Admin.DashBoard');
$response = new Response($view);
return $response->withCookie(cookie('valid', $UserToken, 10));

Laravel JWT Auth fetch user if token

I'm using the jwt-auth package for Laravel. It's working great, but it seems that a user has to be authenticated or not.
For instance some routes do not require authentication, but if the token is present it should still authenticate the user. The parameters I display to user from API can vary based on the type of users access. So admins will get some additional parameters.
Right now it will always just throw token absent. But it should go through as normal and "IF" token is present, process it.
Not sure if I need to create a custom middleware for this.
class JWTAuthIfPresent
{
public function handle($request, Closure $next)
{
if (JWTAuth::getToken()) {
JWTAuth::parseToken()->authenticate();
}
return $next($request);
}
}
This seems to work, but not sure if there is a better way or something already in the existing package.
EDIT:
Also this will not deal with any token issues, like token= or some invalid or expired token. If set it should still process the token normally.
Ok, I was able to figure this out by simple extending the existing auth.
namespace App\Http\Middleware;
use JWTAuth;
use Closure;
use \Tymon\JWTAuth\Middleware\GetUserFromToken;
class JWTAuthIfPresent extends GetUserFromToken
{
public function handle($request, Closure $next)
{
if (JWTAuth::getToken()) {
return parent::handle($request, $next);
}
return $next($request);
}
}

Categories