I want to be able to retrieve the token from the http_request_body as for annoying reasons where I need to send the data from, the token is too long to send as part of the query string, and they don't accept sending headers.
Anyway, I've managed to edit the jwt.auth GetUserFromToken middleware to the following:
if (! $token = $this->auth->setRequest($request)->getToken()) {
if(! $token = $request->get('token') ) {
return $this->respond('tymon.jwt.absent', 'token_not_provided', 400);
}
}
This works, but I am wondering if there is a better way that would be more permanent?
Obviously when I deploy or the package is updated this will be over-ridden.
Is there a way to extend to extend or over-ride this class from within my app, rather than directly in the vendor Middleware?
Thanks!
With the help of #Moeen Basra #apokryfos and this How to override vendor class file?
Managed to extend the Middleware so that it overrides the existing Class and won't be impacted when the app is deployed or the package updated.
Added MyGetUserFromToken.php
namespace App\Overrides\Tymon;
use Tymon\JWTAuth\Middleware\GetUserFromToken;
class MyGetUserFromToken extends GetUserFromToken {
And then in the Kernel
//use Tymon\JWTAuth\Middleware\GetUserFromToken;
use App\Overrides\Tymon\MyGetUserFromToken;
...
'jwt.auth' => MyGetUserFromToken::class,
Hopefully this will then help others also.
Related
I'm trying to invalidate (or remove) a token from JWT but I can't achieve that. First I did something like this answer says Logout issue with Laravel JWT-auth authentication:
JWTAuth::invalidate(JWTAuth::getToken())):
But I get this error:
Non-static method Tymon\JWTAuth\JWT::invalidate() should not be called statically, assuming $this from incompatible context
Then I did something like this:
use Illuminate\Http\Request;
use Tymon\JWTAuth\JWTAuth;
class AuthController extends Controller
{
protected $jwt;
public function __construct(JWTAuth $jwt)
{
$this->jwt = $jwt;
}
public function invalidateToken(Request $request)
{
$this->jwt->parseToken()->invalidate();
return response()->json(array('message' => 'log out'));
}
...
}
But I can still use the token for another request and I can't remove or invalidate it.
What am I doing wrong to invalidate the token?
Edit:
I read another questions from here and issues post from the repo of JWT on github (this is the library I'm using) and I followed all the examples to invalidate or remove the token and I can't still remove or invalidate it .
The blacklist feature works if cache_driver in your .env file is set to something other than array.
Changing it to file worked for me. However, in my particular case, I was using Entrust too, which causes issues when cache_driver is set to file or database. So, had to drop the blacklist/invalidate functionality.
Hope this helps someone.
This is how i think it should look like: $this->jwt->setToken($old_token)->invalidate(true);
JWTAuth::invalidate(old token);
I got the following serivce provider:
class CartServiceProvider extends ServiceProvider {
public function boot() {
}
public function register() {
$this->app->singleton(\Alexxosipov\Cart\Cart::class, function($app) {
return new \Alexxosipov\Cart\Cart($app['request']);
});
}
}
And my Cart class, where I got this:
$this->id = (request()->cookie('cart_id')) ? request()->cookie('cart_id') : false;
But request()->cookie('cart_id') returns encrypted string. If I will do it in any controller, it works fine. Why? What should I do to use it in Cart class?Laravel 5.5
The sequences of Laravel bootstrapping a request is this (v5.6): (CMIIW)
index.php is called
\Illuminate\Foundation\Application created
HttpKernel registered. This register your middlewares
Console Kernel registered. This defines console commands
Exception Handler registered. This defines exception handlers
HttpKernel instantiated. This instantiate all middlewares, plus boot/register all your service providers
Create global request instance. Pass it to HttpKernel to handle incoming request.
Middleware EncryptCookies called, cookies decrypted
Sending request to other middlewares to process
Send request to router, router dispatch to controller
...
Before sending response to browser, cookies encrypted back in EncryptCookies
Cookie is remained encrypted in Step 1 - Step 7. Your CartServiceProvider is trying to obtain a cookie that is yet to be decrypted at Step 6, which is not possible. Consider either
Decrypt the cookie by yourself (using just decrypt), or
Make a middleware to instantiate the cart after EncryptCookies. It's a little bit too early to instantiate cart at the bootstrapping service providers phase.
Edit: Add singleton suggestion
I think you could do this:
Create a new method named loadCartFromRequest($request) in your Cart::class. This method help you load a cart instance from request during the middleware phase.
In your CartServiceProvider, you register a singleton of Cart::class as usual, but no need to read the request here.
Create a middleware, called CartMiddleware. This middleware call app(Cart::class)->loadCartFromRequest($request).
Then at any other places that you need the cart instance, you can access your cart model from app(Cart::class).
I hope I understand your requirement correctly :)
Why? Cookie encryption protects data stored in the client's browser.
The How: Laravel uses the EncryptCookies middleware, this middleware would not yet be processed when your service provider is registered but would be processed for the controller since middlewares are in the routing stack before the request is passed to the controller.
Since I don't know about your cart class and its logic, I can't really recommend what you should do. Perhaps you need to think about when you are passing the Request object to your class.
I am using the Laravel 5.2 Auth system coming up with this command :
php artisan make:auth
Although this works totally fine as is, my goal is to use an external API to perform login, registering and changing password while still being able to use the core function of the Auth class.
So taking the login for example, I want to use something like
function login(ApiController $api) {
// This function return data or error code and message in JSON
$login = $api->login([ $credentials['email'], $credentials['password']]);
if($login->success)
// login successfully like normal Auth would do
else
// redirect to main page with $login->message
}
By the way, I want to pass fields coming up from $login to the Auth class, like we can actually do Auth::user()->email giving us the email, I'd want to set value like "database field" but with my API JSON fields behind
I looked on the Internet and found something to do inside AuthController and something related to ServiceProvider, but I don't know how to follow my exact needs
Adding a custom user provider would help in this case. There is no need to play with AuthController here. Check this Laravel Docs page.
You will need to create a new User Provider which implements Illuminate\Contracts\Auth\UserProvider, specify it in AuthServiceProvider and update your auth config file accordingly.
Here are the links to the framework's default User Providers for reference :
1) DatabaseUserProvider
2) EloquentUserProvider
I ended up coding my own Auth system...
Using session() and Input()
I'm trying to invalidate (or remove) a token from JWT but I can't achieve that. First I did something like this answer says Logout issue with Laravel JWT-auth authentication:
JWTAuth::invalidate(JWTAuth::getToken())):
But I get this error:
Non-static method Tymon\JWTAuth\JWT::invalidate() should not be called statically, assuming $this from incompatible context
Then I did something like this:
use Illuminate\Http\Request;
use Tymon\JWTAuth\JWTAuth;
class AuthController extends Controller
{
protected $jwt;
public function __construct(JWTAuth $jwt)
{
$this->jwt = $jwt;
}
public function invalidateToken(Request $request)
{
$this->jwt->parseToken()->invalidate();
return response()->json(array('message' => 'log out'));
}
...
}
But I can still use the token for another request and I can't remove or invalidate it.
What am I doing wrong to invalidate the token?
Edit:
I read another questions from here and issues post from the repo of JWT on github (this is the library I'm using) and I followed all the examples to invalidate or remove the token and I can't still remove or invalidate it .
The blacklist feature works if cache_driver in your .env file is set to something other than array.
Changing it to file worked for me. However, in my particular case, I was using Entrust too, which causes issues when cache_driver is set to file or database. So, had to drop the blacklist/invalidate functionality.
Hope this helps someone.
This is how i think it should look like: $this->jwt->setToken($old_token)->invalidate(true);
JWTAuth::invalidate(old token);
I am currently experimenting with the new Laravel 5 and got the authentication to work (register/login).
To get the authenticated user in my controller I currently inject Guard into the controller action:
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\Guard;
class ClientController extends Controller {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index(Guard $auth)
{
return view('client.index', ['user' => $auth->user()]);
}
...
First Question: Is this the recommended way?
Second Question: How would I go about implementing some kind of roles/permissions? Something like client.edit, client.add, ... Does Larval 5 offer some kind of convenience here?
How would I set the necessary role/permission for a route/controller action?
I am thinking that I might need to write my own middleware for that. Any suggestions on how to approach the problem?
After spending some more time on Laravel 5 I can an answer my own question:
Is injecting Guard the recommended way? No: If you need to access Auth in your view, you can do so already like this:
#if( Auth::check() )
Current user: {{ Auth::user()->name }}
#endif
This uses the Auth facade. A list of all available facades is in config/app.php under aliases:
What if I need Auth in my controller? Injecting an instance of Guard like shown in the question works, but you don't need to. You can use the Auth facade like we did in the template:
public function index()
{
if(\Auth::check() && \Auth::user()->name === 'Don') {
// Do something
}
return view('client.index');
}
Be aware that the \ is needed before the facade name since L5 is using namespaces.
I want to have permissions/roles using the new auth mechanism in L5: I implemented a lightweight permission module using the new middleware, it is called Laraguard. Check it out on Github and let me know what you think: https://github.com/cgrossde/Laraguard
UPDATE: For the sake of completeness I want to mention two more projects. They provide everything you need to save roles and permissions in the DB and work perfectly together with Laraguard or on their own:
https://github.com/caffeinated/shinobi
https://github.com/romanbican/roles
If you want make your own custom authentification, you need to keep the User model from Laravel 5 with all the dependency. After you will be able to login your user in your controller. Dont forget to put (use Auth;) after the namespace of your controller.