markitosgv / jwtrefreshtokenbundle Goto Github PK
View Code? Open in Web Editor NEWImplements a Refresh Token system over Json Web Tokens in Symfony
License: MIT License
Implements a Refresh Token system over Json Web Tokens in Symfony
License: MIT License
Since LexikJWTAuthenticationBundle 1.7.0
See lexik/LexikJWTAuthenticationBundle#200
This bundle is not working anymore.
An Exception was thrown while handling: Catchable Fatal Error: Argument 1 passed to Gesdinet\JWTRefreshTokenBundle\Request\RequestRefreshToken::getRefreshToken() must be an instance of Symfony\Component\HttpFoundation\Request, null given, called in gesdinet\jwt-refresh-token-bundle\EventListener\AttachRefreshTokenOnSuccessListener.php on line 44 and defined
I use jwt token for auth and I had to change user_identity_field
to email. And after that when I try call /api/token/refresh
I have 401 status code. Because for refresh token entity in username
property saved username data from user
my config
lexik_jwt_authentication:
private_key_path: '%jwt_private_key_path%'
public_key_path: '%jwt_public_key_path%'
pass_phrase: '%jwt_key_pass_phrase%'
token_ttl: '%jwt_token_ttl%'
user_identity_field: email
gesdinet_jwt_refresh_token:
ttl: '%jwt_refresh_token_ttl%'
ttl_update: true
user_provider: security.user.provider.concrete.chain_provider
and my security
security:
encoders:
AppBundle\Entity\User:
algorithm: bcrypt
AppBundle\Entity\Admin:
algorithm: bcrypt
providers:
chain_provider:
chain:
providers: [admins, entity_provider]
admins:
entity:
class: AppBundle:Admin
property: email
entity_provider:
entity:
class: AppBundle:User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
refresh:
pattern: ^/api/token/refresh
stateless: true
anonymous: true
api_admin:
pattern: ^/api/admin
stateless: true
anonymous: false
provider: chain_provider
guard:
authenticators:
- app.jwt_token_authenticator
login:
pattern: ^/api/login
stateless: true
anonymous: true
form_login:
check_path: /api/login_check
require_previous_session: false
username_parameter: _email
password_parameter: _password
success_handler: custom
failure_handler: lexik_jwt_authentication.handler.authentication_failure
now /api/token/refresh
I have response
{
"code": 401,
"message": "Bad credentials"
}
because \Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken
have username
data from user, but in my config for lexik_jwt_authentication
I changed it
user_identity_field: email
How to apply user_identity_field: email
to refresh token ?
Instead of generating random token and storing it to database, think about using another JWT as a refresh token.
Refresh token generated this way will have the expiry information in it, so no database access is needed for validation, except for blacklisting which could be optional.
Hi all,
I think it can be usefull to have an Event dispatched before the RefreshToke is persisted to add some data inthe Entity.
My current usecase is that I want to store the userAgent of the user's device when s/he connnect for the first time. Currently I do that listening to lexik_jwt_authentication.on_authentication_success adding my data and persisting again the RefreshToken. But that makes 2 DB operations where only one is necessary.
Having an event in the Gesdinet\JWTRefreshTokenBundle\Doctrine\RefreshTokenManager::save
or AttachRefreshTokenOnSuccessListener::attachRefreshToken
should allow to add some data to the Entity before persist.
Regards
Every time I go to refresh the token, every time the refresh_token does not change, how to change it
Hi,
I would like the user session expire XXX minutes after the last action on the application by the user.
If I understand correctly, ttl_update: true
seems to expend the refresh token ttl only when we call the token/refresh
service?
Is it possible to expend the refresh token ttl automatically on every call of any webservices?
Thanks
Seb
Hi,
Is there anyway to have a proxy action in my controller to add the annotation in order to get the refresh endpoint documented on my APIDOC ?
I am using PHP7.1 / Symfony 4.0
Thanks
Vincent
Hi,
After installing and configuring JWTRefreshTokenBundle successfully, I have this error when I try to do the curl request:
curl -X POST -d refresh_token="xxxx4b54b0076d2fcc5a51a6e60c0fb83b0bc90b47e2c886accb70850795fb311973c9d101fa0111f12eec739db063ec09d7dd79331e3148f5fc6e9cb362xxxx" 'http://xxxx/token/refresh'
The error:
Neither the property "email" nor one of the methods "getEmail()", "email()", "ismail()", "hasEmail()", "__get()" exist and have public access in class "Symfony\\Component\\Security\\Core\\User\\User"
I used FOSUserBundle with LexikJWTAuthenticationBundle.
Maybe I have to configure the user provider of this bundle but I didn't find the configuration.
My config:
# app/config/security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
Symfony\Component\Security\Core\User\User:
algorithm: bcrypt
cost: 12
...
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
in_memory:
memory:
users:
xxxx: { password: xxxx, roles: 'ROLE_ADMIN' }
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
default:
pattern: ^/api/doc
provider: in_memory
anonymous: ~
http_basic:
realm: "xxxxx"
provider: in_memory
authenticate:
pattern: ^/v1/authenticate
stateless: true
anonymous: true
form_login:
check_path: /v1/authenticate
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
require_previous_session: false
refresh:
pattern: ^/v1/token/refresh
stateless: true
anonymous: true
api:
pattern: ^/v1
provider: fos_userbundle
stateless: true
anonymous: true
lexik_jwt: ~
access_control:
- { path: ^/api/doc, roles: ROLE_ADMIN }
- { path: ^v1/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY }
# app/config/routing.yml
NelmioApiDocBundle:
resource: "@NelmioApiDocBundle/Resources/config/routing.yml"
prefix: /api/doc
fos_user:
resource: "@FOSUserBundle/Resources/config/routing/all.xml"
api_login_check:
path: /v1/authenticate
gesdinet_jwt_refresh_token:
path: /v1/token/refresh
defaults: { _controller: gesdinet.jwtrefreshtoken:refresh }
home:
prefix: /
resource: AppBundle\Controller\HomeController
...
Hi.
I'm try to implement the last release that has support for symfony 4, but I'm get this error
Controller "gesdinet.jwtrefreshtoken" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?
It is about services, have you updated the services and implemented the autowire? and of course make the services public.
Will be support for Symfony 4 added? lexik/LexikJWTAuthenticationBundle
supports it.
I think is a good enhancement to make this bundle can handle many refresh tokens for different sessions. Do you have any idea how can implement this?
Hi, thanks for your excellent work.
I have a listener when ask for the JWT token: JWTCreatedListener.
But when i request to refresh the token it gives to me this error:
{ "error": { "code": 500, "message": "Internal Server Error", "exception": [ { "message": "Call to a member function getRole() on string",
...
I have this method getRole() for some tasks.
This is the Listener code:
` public function onJWTCreated(JWTCreatedEvent $event)
{
$request = $this->requestStack->getCurrentRequest();
// Work of roles
$roles = $event->getUser()->getRoles();
$role_length = count($roles);
$role_list = array();
for ($i=0; $i <$role_length ; $i++) {
array_push($role_list,$roles[$i]->getRole());
}
$payload = $event->getData();
$payload['ip'] = $request->getClientIp();
$payload['roles'] = $role_list;
$event->setData($payload);
}`
Any suggest? Thanks
I generate jwt token using "lexik_jwt_authentication.encoder" service. In JWTRefreshTokenBundle's readme file I see that LexikJWTAuthenticationBundle now should returns a JWT Token and a Refresh Token data.
$token = $this->get('lexik_jwt_authentication.encoder')
->encode([
'username' => $user->getUsername(),
'exp' => (new \DateTime('+40 seconds'))->getTimestamp(),
]);
$token variable does not contains refresh token. In database, refresh_tokens table does not contains any token.
Hi. When I try to renew a token which is expired :
Catchable Fatal Error: Object of class Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken could not be converted to string
=> vendor/gesdinet/jwt-refresh-token-bundle/Service/RefreshToken.php at line 70
I guess toString method should be implemented.
I want to extend the default implementation of RefreshToken
in order to add some attributes. If I configure my class following the documentation I got the following error:
[Doctrine\DBAL\Exception\InvalidFieldNameException]
An exception occurred while executing 'SELECT r0_.id AS id_0, r0_.refresh_token AS refresh_token_1, r0_.username AS username_2, r0_.valid AS valid_3, c1_.custom_attr AS
impersonator_4 FROM acme_jwt_refresh_token c1_ LIMIT 1':
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'r0_.id' in 'field list'
[Doctrine\DBAL\Driver\PDOException]
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'r0_.id' in 'field list'
[PDOException]
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'r0_.id' in 'field list'
It happens both on refresh_token endpoint or when executing a query like bin/console doctrine:query:dql "SELECT rf FROM Acme:RefreshToken\RefreshToken rf" --max-result=1
In order to fix it the bundle must have an @MappedSuperclass
class.
I will open a pull-request with the fix soon.
Aditional info:
config.yml
gesdinet_jwt_refresh_token:
refresh_token_entity: 'Acme\Model\RefreshToken\RefreshToken'
RefreshToken.php
<?php
declare(strict_types = 1);
namespace Acme\Model\RefreshToken;
use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken as BaseRefreshToken;
class RefreshToken extends BaseRefreshToken
{
/**
* @var string
*/
protected $customAttr;
public function customAttr() : ?string
{
return $this->customAttr;
}
public function setcustomAttr(string $customAttr) : void
{
$this->customAttr = $customAttr;
}
}
Doctrine mapping:
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping
xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://raw.github.com/doctrine/doctrine2/master/doctrine-mapping.xsd">
<entity
name="Acme\Model\RefreshToken\RefreshToken"
table="acme_jwt_refresh_token"
repository-class="Gesdinet\JWTRefreshTokenBundle\Entity\RefreshTokenRepository">
<field name="customAttr" column="custom_attr" type="string" length="255" nullable="true" />
</entity>
</doctrine-mapping>
Hi all,
Please add another condition which checks the header of request for a refresh token:
public static function getRefreshToken(Request $request)
{
$refreshTokenString = null;
if (false !== strpos($request->getContentType(), 'json')) {
$content = $request->getContent();
$params = !empty($content) ? json_decode($content, true) : array();
$refreshTokenString = isset($params['refresh_token']) ? trim($params['refresh_token']) : null;
} elseif (null !== $request->get('refresh_token')) {
$refreshTokenString = $request->get('refresh_token');
} elseif (null !== $request->request->get('refresh_token')) {
$refreshTokenString = $request->request->get('refresh_token');
} elseif (null !== $request->headers->get('authorization')) { // TODO: header check
$refreshTokenString = $request->headers->get('authorization');
$refreshTokenString = str_replace("Basic ", "", $refreshTokenString);
}
return $refreshTokenString;
}
This will allow the users of @juztcode/angular-auth use this bundle with Angular without pain.
Hello folks,
i found out that a the ttl of JWTToken is not expanded, when it is used in api calls. This would have been the best solution in my opinion. But now i saw this bundle at i still cant find a solution, where the client can be "dumb".
This is what i understood:
In this scenario, the client contains to much intelligence. Did i miss something or got something completely wrong?
Kind regards
Max
Hello,
as per api-platform's recommedations, I am using Doctrine user provider in my API.
So, my User entity looks like this:
// src/Api/Entity/User.php
namespace App\Api\Entity;
class User implements UserInterface, \Serializable {...}
Now I have no idea how to configure user_provider. I tried to set it like this:
# config/packages/gesindet_jwt_refresh_token.yaml
gesdinet_jwt_refresh_token:
user_provider: app.api.entity.user
But I'm getting this error:
Type error: Argument 1 passed to ...\RefreshTokenProvider::setCustomUserProvider() must implement interface ...\UserProviderInterface, null given
Do you have any idea how do I set user_provider path properly, please?
Can we customize the parameter "refresh_token" when calling the route to refresh the JWT , I would like it to be camelCase as the rest of the API I m building.
Same question about the response, to return "token" and "refreshToken" instead of "refresh_token"
Thanks
Vincent
API clients can logout deleting its refresh_token. But this only works in client side, i mean, if someone has got refresh_token could do a login again.
The idea is to set an endpoint like /api/token/revoke which accepts a POST with refresh_token to revoke access.
Add another endpoint to revoke all tokens related to a user.
To call both endpoints user needs to be logged, of course. In other words, this endpoint has to be under JWT firewall.
I am using this bundle and it works perfectly and is easy to installe (great work guys ! Thanks !)
Anyway, i've noticed that tokens are actually stored in plain text in the db. I think this could be a weakness in any app if there is an fraudulous access on database.
I did not found any information on how to enable an encoding of the refresh tokens. Does anybody have an information on this ?
I would also suggest to add a buil-in solution for the bundle to easily add an encoder.
Thanks
Can not configure multiple providers and use different urls to access each by using the chain and the same username in different providers it ends using always first success provider.
I think it will require to redesign bundle to be able to provide configuration and different urls for different providers
It would be nice if the database read/write stuff would be abstracted so other systems like Propel2 can be integrated instead of Doctrine2. This also includes that Doctrine2 is no more required to use this bundle.
A good example is how FOSUserBundle is working, see https://github.com/FriendsOfSymfony/FOSUserBundle
Hello,
I'm new in symfony and and try to set HWTRefreshTokenBundle with JTW Lexik.
In jwt I have own Entity
namespace SharedBundle\Security;
final class User implements \Lexik\Bundle\JWTAuthenticationBundle\Security\User\JWTUserInterface
{
private $username;
private $roles;
private $name;
public function __construct($username, array $roles, $email, $name)
{
$this->username = $username;
$this->roles = $roles;
$this->email = $email;
$this->name = $name;
}
public static function createFromPayload($username, array $payload)
{
return new self(
$username,
$payload['roles'], // Added by default
$payload['email'], // Custom
$payload['name']
);
}
/**
* {@inheritdoc}
*/
public function getUsername()
{
return $this->username;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->name;
}
/**
* {@inheritdoc}
*/
public function getRoles()
{
return $this->roles;
}
...
In listener I add custom data:
public function onJWTCreated(JWTCreatedEvent $event) {
$request = $this->requestStack->getCurrentRequest();
$payload = $event->getData();
$user = $event->getUser();
$payload['name'] = $user->getName();
$payload['email'] = $user->getEmail();
$payload['ip'] = $request->getClientIp();
$event->setData($payload);
}
But when I try to refresh token I get error:
[Mon May 29 22:07:36 2017] 127.0.0.1:56078 [200]: /api/token/refresh
[Mon May 29 22:13:52 2017] PHP Fatal error: Call to undefined method Symfony\Component\Security\Core\User\User::getName() in .../application/be/src/SharedBundle/EventListener/JWTCreatedListener.php on line 33
Segmentation fault
When I throw email and name from payload token is created but without this data, and return only default role ROLE_USER
without ROLE_ADMIN
.
I'tried to use refresh_token_entity: SharedBundle\Security\User
but without result :/
How can I implemet additional fields in payload?
Hi,
I am getting forbidden 403 while doing the refresh_token
curl -X POST http://localhost:8083/api/token/refresh --data refresh_token=9be6a1654513bab76c3c0da96c4cb8c01abaad8d4a3b53a7f1e3ebe89caf034fbeb60f562876216720b173e01649a362f3711233f994aa11a722a82fff15d399
routing.yml
gesdinet_jwt_refresh_token:
path: /api/token/refresh
defaults: { _controller: gesdinet.jwtrefreshtoken:refresh }
security.yml
firewalls: refresh: pattern: ^/api/token/refresh stateless: true anonymous: true - { path: ^/api/token/refresh, role: IS_AUTHENTICATED_ANONYMOUSLY }
config.yml
gesdinet_jwt_refresh_token:
user_provider: fos_user.user_provider.username_email
ttl_update: false
firewall: api
I am using the refresh token.
Thanks
Hi,
If you want to use this bundle with another entity manager instead of default, this fails.
Then you need to override in your app/config/services.yml gesdinet.jwtrefreshtoken.refresh_token_manager service, injecting your custom entity_manager like this:
gesdinet.jwtrefreshtoken.refresh_token_manager:
class: Gesdinet\JWTRefreshTokenBundle\Doctrine\RefreshTokenManager
arguments: [@doctrine.orm.custom_entity_manager, %gesdinet.jwtrefreshtoken.refresh_token.class%]
Another example: if you are using FOSUserBundle you maybe want to inject fos_user.entity_manager service like this:
gesdinet.jwtrefreshtoken.refresh_token_manager:
class: Gesdinet\JWTRefreshTokenBundle\Doctrine\RefreshTokenManager
arguments: [@fos_user.entity_manager, %gesdinet.jwtrefreshtoken.refresh_token.class%]
To do:
Scenario:
Auth with credentials for user 1:
token: abc
refresh_token: xyz
Get new token with refresh_token:
token: def
refresh_token: xyz
token expired, auth with credentials for user 1:
token: ghi
refresh_token: xyz
optionally login from another browser with user 1 credentials:
token: jkl
refresh_token: xyz
I don't think that in step 3) and/or 4) the same token should be returned. Every credentials authentication should generate a new refresh_token.
Thanks for the hard work you put in this bundle. Do you have any plans to make it compatible with Symfony 3.0 in the near future?
This bundle "links" user table and refresh token table with username field.
What's happened if users swap their usernames ?
Maybe I miss some codes but I see a real security issue.
Why do you not use relationship with foreign key between user table and refresh token table ?
Best regards.
In Lexik you can customize the data response using event listeners. The way the refresh token is added breaks our REST API model and I need to be able to customize the response as I can with Lexik. Are there events I can subscribe to in order to make sure the refresh token is placed in the right part of the response instead of just appended to it?
Thank you!
Is there any possibility to use custom RefreshTokenManager?
I use jwt token for auth and I had to change user_identity_field
to email. And after that when I try call /api/token/refresh
I have 401 status code. Because for refresh token entity in username
property saved username data from user
my config
lexik_jwt_authentication:
private_key_path: '%jwt_private_key_path%'
public_key_path: '%jwt_public_key_path%'
pass_phrase: '%jwt_key_pass_phrase%'
token_ttl: '%jwt_token_ttl%'
user_identity_field: email
gesdinet_jwt_refresh_token:
ttl: '%jwt_refresh_token_ttl%'
ttl_update: true
user_provider: security.user.provider.concrete.chain_provider
and my security
security:
encoders:
AppBundle\Entity\User:
algorithm: bcrypt
AppBundle\Entity\Admin:
algorithm: bcrypt
providers:
chain_provider:
chain:
providers: [admins, entity_provider]
admins:
entity:
class: AppBundle:Admin
property: email
entity_provider:
entity:
class: AppBundle:User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
refresh:
pattern: ^/api/token/refresh
stateless: true
anonymous: true
api_admin:
pattern: ^/api/admin
stateless: true
anonymous: false
provider: chain_provider
guard:
authenticators:
- app.jwt_token_authenticator
login:
pattern: ^/api/login
stateless: true
anonymous: true
form_login:
check_path: /api/login_check
require_previous_session: false
username_parameter: _email
password_parameter: _password
success_handler: custom
failure_handler: lexik_jwt_authentication.handler.authentication_failure
now /api/token/refresh
I have response
{
"code": 401,
"message": "Bad credentials"
}
because \Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken
have username
data from user, but in my config for lexik_jwt_authentication
I changed it
user_identity_field: email
How to apply user_identity_field: email
to refresh token ?
Is it possible to use an existing refreshToken
field in an own User
entity instead of an additional table?
Attempting to get Token ,the credentials are successful but then getting this failure:
The class 'Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken' was not found in the chain configured namespaces AppBundle\Entity
Setup:
routing.yml
gesdinet_jwt_refresh_token:
path: /api/v1/token/refresh
defaults: { _controller: gesdinet.jwtrefreshtoken:refresh }
security.yml
gettoken:
pattern: ^/api/v1/getToken$
stateless: true
gfreeau_get_jwt:
# this is the default config
username_parameter: username
password_parameter: password
post_only: true
authentication_provider: security.authentication.provider.dao
user_checker: security.user_checker
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
refresh:
pattern: ^/api/v1/token/refresh
stateless: true
anonymous: true
- { path: ^/api/v1/getToken, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/v1/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, role: ROLE_ADMIN }
parameters.yml
jwt_private_key_path: "%kernel.root_dir%/var/jwt/private.pem" # ssh private key path
jwt_public_key_path: "%kernel.root_dir%/var/jwt/public.pem" # ssh public key path
jwt_key_pass_phrase: 'redacted' # ssh key pass phrase
jwt_cookie_name: 'jwt_token'
jwt_refresh_token_cookie_name: 'jwt_refresh_token'
jwt_token_ttl: 86400
Stack Trace
Trace
in vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/MappingException.php at line 37 -
*/
public static function classNotFoundInNamespaces($className, $namespaces)
{
return new self("The class '" . $className . "' was not found in the ".
"chain configured namespaces " . implode(", ", $namespaces));
}
at MappingException ::classNotFoundInNamespaces ('Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken', array('AppBundle\Entity'))
in vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php at line 112 +
at MappingDriverChain ->loadMetadataForClass ('Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken', object(ClassMetadata))
in vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php at line 151 +
at ClassMetadataFactory ->doLoadMetadata (object(ClassMetadata), null, false, array())
in vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php at line 332 +
at AbstractClassMetadataFactory ->loadMetadata ('Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken')
in vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php at line 78 +
at ClassMetadataFactory ->loadMetadata ('Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken')
in vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php at line 216 +
at AbstractClassMetadataFactory ->getMetadataFor ('Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken')
in vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 281 +
at EntityManager ->getClassMetadata ('Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken')
in vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php at line 44 +
at DefaultRepositoryFactory ->getRepository (object(EntityManager), 'Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken')
in vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 698 +
at EntityManager ->getRepository ('Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken')
in var/cache/dev/appDevDebugProjectContainer.php at line 6660 +
at DoctrineORMEntityManager_0000000064894caa000000010173686ed16a19f69a8f3c00cb83b6d77e875531 ->getRepository ('Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken')
in vendor/gesdinet/jwt-refresh-token-bundle/Doctrine/RefreshTokenManager.php at line 33 +
at RefreshTokenManager ->__construct (object(DoctrineORMEntityManager_0000000064894caa000000010173686ed16a19f69a8f3c00cb83b6d77e875531), 'Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken')
in var/cache/dev/appDevDebugProjectContainer.php at line 2053 +
at appDevDebugProjectContainer ->getGesdinet_Jwtrefreshtoken_RefreshTokenManagerService ()
in vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php at line 274 +
at Container ->get ('gesdinet.jwtrefreshtoken.refresh_token_manager')
in var/cache/dev/appDevDebugProjectContainer.php at line 2066 +
at appDevDebugProjectContainer ->getGesdinet_Jwtrefreshtoken_SendTokenService ()
in vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php at line 274 +
at Container ->get ('gesdinet.jwtrefreshtoken.send_token')
in var/cache/dev/classes.php at line 2264 +
at ContainerAwareEventDispatcher ->lazyLoad ('lexik_jwt_authentication.on_authentication_success')
in var/cache/dev/classes.php at line 2233 +
at ContainerAwareEventDispatcher ->getListeners ('lexik_jwt_authentication.on_authentication_success')
in vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php at line 241 +
at TraceableEventDispatcher ->preProcess ('lexik_jwt_authentication.on_authentication_success')
in vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php at line 131 +
at TraceableEventDispatcher ->dispatch ('lexik_jwt_authentication.on_authentication_success', object(AuthenticationSuccessEvent))
in vendor/lexik/jwt-authentication-bundle/Security/Http/Authentication/AuthenticationSuccessHandler.php at line 51 +
at AuthenticationSuccessHandler ->onAuthenticationSuccess (object(Request), object(UsernamePasswordToken))
in vendor/gfreeau/get-jwt-bundle/Gfreeau/Bundle/GetJWTBundle/Security/Firewall/GetJWTListener.php at line 143 +
at GetJWTListener ->onSuccess (object(GetResponseEvent), object(Request), object(UsernamePasswordToken))
in vendor/gfreeau/get-jwt-bundle/Gfreeau/Bundle/GetJWTBundle/Security/Firewall/GetJWTListener.php at line 117 +
at GetJWTListener ->handle (object(GetResponseEvent))
in var/cache/dev/classes.php at line 3093 +
at Firewall ->onKernelRequest (object(GetResponseEvent), 'kernel.request', object(TraceableEventDispatcher))
at call_user_func (array(object(Firewall), 'onKernelRequest'), object(GetResponseEvent), 'kernel.request', object(TraceableEventDispatcher))
in vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php at line 61 +
at WrappedListener ->__invoke (object(GetResponseEvent), 'kernel.request', object(ContainerAwareEventDispatcher))
at call_user_func (object(WrappedListener), object(GetResponseEvent), 'kernel.request', object(ContainerAwareEventDispatcher))
in var/cache/dev/classes.php at line 2167 +
at EventDispatcher ->doDispatch (array(object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener)), 'kernel.request', object(GetResponseEvent))
in var/cache/dev/classes.php at line 2082 +
at EventDispatcher ->dispatch ('kernel.request', object(GetResponseEvent))
in vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php at line 136 +
at TraceableEventDispatcher ->dispatch ('kernel.request', object(GetResponseEvent))
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php at line 129 +
at HttpKernel ->handleRaw (object(Request), '1')
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php at line 68 +
at HttpKernel ->handle (object(Request), '1', true)
in var/bootstrap.php.cache at line 1447 +
at Kernel ->handle (object(Request))
in web/app.php at line 29 +
Hi,
I'm using mongodb, when i tried to install latest version ((>=v0.5.1), I am getting following error.
Script cache:clear returned with error code 255
!!
!! Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineOrmMappingsPass" from namespace "Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler".
!! Did you forget a "use" statement for another namespace? in /var/www/html/vendor/gesdinet/jwt-refresh-token-bundle/DependencyInjection/Compiler/DoctrineMappingsCompilerPass.php:55
!! Stack trace:
!! #0 /var/www/html/vendor/gesdinet/jwt-refresh-token-bundle/DependencyInjection/Compiler/DoctrineMappingsCompilerPass.php(32): Gesdinet\JWTRefreshTokenBundle\DependencyInjection\Compiler\DoctrineMappingsCompilerPass->getORMCompilerPass(Array)
!! #1 /var/www/html/vendor/symfony/dependency-injection/Compiler/Compiler.php(95): Gesdinet\JWTRefreshTokenBundle\DependencyInjection\Compiler\DoctrineMappingsCompilerPass->process(Object(Symfony\Component\DependencyInjection\ContainerBuilder))
!! #2 /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php(736): Symfony\Component\DependencyInjection\Compiler\Compiler->compile(Object(Sy in /var/www/html/vendor/gesdinet/jwt-refresh-token-bundle/DependencyInjection/Compiler/DoctrineMappingsCompilerPass.php on line 55
!!
Script @auto-scripts was called via post-update-cmd
I don't have orm installed, instead I am using mongodb odm.
Hi folks,
Recently i've created a new 3.0 branch. Now it works with both Symfony 2.8 and 3.0, but breaks 2.5 - 2.7 support.
Do you think the best option is maintan two branches separately? Or maybe the best option is try to support both in master?
Our principle issue is that interface SimplePreAuthenticatorInterface is moved from Core to Http namespace.
use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;
This interface is used in Gesdinet\JWTRefreshTokenBundle\Security\Authenticator\RefreshTokenAuthenticator
Do you know the best way to "choose" one or another interface depends on Symfony version?
Hi friends,
I think this bundle can't depends on FOSUserBundle.
I think is better to rename entity UserRefreshToken to RefreshToken, and save username in this entity as string.
The entity then will have 4 fields:
id, refresh_token, username, valid
With username we could revoke every refresh_token, for example if a user request to close sessions.
What do you think?
Hi.
I'm trying to store refresh tokens in a mongodb, so I'm extend Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken
but in this case nothing is working because of @UniqueEntity
annotation on the base class. So I need to copy all methods to my class.
It would be great, if I can avoid this copy-paste.
Thanks
Here is what I got when trying to login
An exception occurred while executing 'SELECT t1.id AS id_2, t1.refresh_token AS refresh_token_3, t1.username AS username_4, t1.valid AS valid_5 FROM jwt_refresh_token t1 WHERE t0.refresh_token = ?' with params ["a94eca429273a21f39fc2374fb3984b9b392910a17afeb02e95627066e1d0dd983048a562780456d5b186148fa27acbda27db4821ab18d313314ac3a9107b025"]:
Hi,
i need to generate a new refresh token when user changes it's username because in that case old refresh token becomes invalid. I can generate JWT token with $token = $this->get('lexik_jwt_authentication.jwt_manager')->create($user);, but can't manage to do the same with refresh token. Am i missing something, or there is no way to do it?
Do first unit tests
After installing the bundle and configuring it as indicated in Readme, whenever I run token refresh with the refresh token i get this error
C:\Users\hp 250>curl -X POST -d refresh_token="9e44afc3b1e45aba95018f29df22fb92e
b3d5416a17289fa674b9bbe106595c5a3426e72c5ca9b93975d9bc070b5cd105663c27ae7a206fbb
be0d1b370d78855" "http://127.0.0.1/xxx/web/app_dev.php/api/token/ref
resh"
{"code":401,"message":"Invalid credentials"}
{
"code": 401,
"message": "Invalid credentials"
}
here is my parameters.yml
parameters:
database_host: 127.0.0.1
database_port: null
database_name: symfony
database_user: root
database_password: null
mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: null
mailer_password: null
secret: ThisTokenIsNotSoSecretChangeIt
jwt_private_key_path: '%kernel.root_dir%\var\jwt\private.pem' # ssh private key path
jwt_public_key_path: '%kernel.root_dir%\var\jwt\public.pem' # ssh public key path
jwt_key_pass_phrase: 'happyapi' # ssh key pass phrase if present
jwt_token_ttl: 3600 #seconds
And here is my config.yml
imports:
- { resource: security.yml }
- { resource: services.yml }
- { resource: "@KasualJobsBundle/Resources/config/services.yml" }
parameters:
locale: en
framework:
#esi: ~
#translator: { fallbacks: ["%locale%"] }
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
# handler_id set to null will use default session handler from php.ini
handler_id: ~
save_path: "%kernel.root_dir%/../var/sessions/%kernel.environment%"
fragments: ~
http_method_override: true
assets: ~
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
doctrine:
dbal:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
# path: "%database_path%"
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }
lexik_jwt_authentication:
private_key_path: %jwt_private_key_path%
public_key_path: %jwt_public_key_path%
pass_phrase: %jwt_key_pass_phrase%
token_ttl: %jwt_token_ttl%
And here is my security.yml
security:
encoders:
KasualJobsBundle\Entity\User: plaintext
Symfony\Component\Security\Core\User\User: plaintext
providers:
in_memory:
memory:
users:
[email protected]:
password: 123
roles: 'ROLE_ADMIN'
my_db_provider:
entity:
class: KasualJobsBundle:User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login_admin:
pattern: ^/api/admin/login
stateless: true
anonymous: true
provider: in_memory
form_login:
check_path: /api/admin/login_check
require_previous_session: false
username_parameter: _username
password_parameter: _password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api_admin:
pattern: ^/api/admin
stateless: true
lexik_jwt:
authorization_header:
enabled: true
prefix: Bearer
query_parameter:
enabled: true
name: bearer
login:
pattern: ^/api/login
stateless: true
anonymous: true
provider: in_memory
form_login:
check_path: /api/login_check
require_previous_session: false
username_parameter: _username
password_parameter: _password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api
stateless: true
lexik_jwt:
authorization_header: # check token in Authorization Header
enabled: true
prefix: Bearer
query_parameter: # check token in query string parameter
enabled: true
name: bearer
refresh:
pattern: ^/api/token/refresh
stateless: true
anonymous: true
access_control:
- { path: ^/api/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/admin, roles: [ ROLE_ADMIN ]}
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
And here are my routes
api:
path: /api
defaults: { _controller: KasualJobsBundle:Default:secureResource }
api_login:
path: /api/login
defaults: { _controller: KasualJobsBundle:Default:index }
api_login_check:
path: /api/login_check
gesdinet_jwt_refresh_token:
path: /api/token/refresh
defaults: { _controller: gesdinet.jwtrefreshtoken:refresh }
The current implementation to refresh JWT tokens is not safe. When a user presents a refresh token, the only check that occurs is whether the user provider can load the user. If a user is loadable, it is granted a new access token.
But the authenticator should also check if the loaded user is still allowed to access the application. For example, users that implement the AdvancedUserInterface should be checked whether their account is enabled, is not locked and is not expired. Other means of authentication may have other requirements (e.g. for OAuth accounts, check whether the correct permissions are still present).
Currently, this bundle will happily give out new access tokens to users who have been disabled, expired, etc.
I think there should be some way to hook into the authenticator to provide this logic. Or perhaps the authenticator in this bundle should delegate authentication to some other authentication provider.
Currently I am using a compiler pass to overwrite the authenticator provided in this bundle with my own. That's a bit of a hackish solution.
Hi,
Function that generate refresh token is this
bin2hex(openssl_random_pseudo_bytes(64));
I think is a good way to create a secure random string. But maybe its not unique. Because of this I ask for username when you need to refresh token.
Do you think is possible if we have so many database users that two valid refresh tokens be repeated?
I have custom entity which extends from the RefreshToken
class. When updating the schema, I get two tables: refresh_tokens
and myname_refresh_tokens
.
I currently installed JWTRefreshTokenBundle and it throws and error as:
Compile Error: Cannot use Gesdinet\JWTRefreshTokenBundle\Service\RefreshToken as RefreshToken because the name is already in use.
I think the issue occurred in the latest pull. I already used the bundle, but at that time it worked fine. I am using Symfony3.4
Can we implement multiple-custom providers support for this bundle?
something like
refresh:
pattern: ^/api/token/refresh
stateless: true
anonymous: true
provider: custom_admin
refresh:
pattern: ^/api/client/token/refresh
stateless: true
anonymous: true
provider: custom_client
refresh:
pattern: ^/api/supplier/token/refresh
stateless: true
anonymous: true
provider: custom_supplier
solved by using chain provider in config
user_provider: security.user.provider.concrete.chain_provider
Is it possible to use a chained user provider? E.g. A couple of default users in memory and some from FosUserBundle ?
Not a huge deal as I can just load those in as fixtures, but I was just curious because the user provider needs to be defined as a service ID it seems.
I've installed the Bundle following the instructions but the /api/token/refresh doesn't update the expiration date into the column valid
of the database table refresh_tokens
.
It returns the token
and refresh_token
json correctly but the date isn't updated.
I'm I doing something wrong?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.