Giter Site home page Giter Site logo

jwtrefreshtokenbundle's People

Contributors

cezarystepkowski avatar chalasr avatar chosroes avatar chris53897 avatar derzkiy avatar digitalkaoz avatar dragosprotung avatar elgovanni avatar fastnloud avatar fd6130 avatar gregurco avatar heer0 avatar igorut avatar jayfrown avatar jdecool avatar juliangut avatar kix avatar markitosgv avatar mbabker avatar misaert avatar norkunas avatar paulchubatyy avatar piotrkreft avatar razachohan avatar ricardodevries avatar sandermarechal avatar sh41 avatar sylvainmetayer avatar webignition avatar wouter-toppy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jwtrefreshtokenbundle's Issues

Not working with LexikJWTAuthenticationBundle 1.7.0

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

JWTRefreshTokenBundle change user_identity_field

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 ?

Why database access at all, use JWT

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.

Event before RefreshToken is persisted

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

Expand Refresh Token TTL on every calls

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

Neither the property email nor ... exist and have public access in class Symfony Core User

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
...

The refreshToken service doesn't work

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.

Symfony 4

Will be support for Symfony 4 added? lexik/LexikJWTAuthenticationBundle supports it.

Multiple sessions

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?

Throws error 500: Call to a member function xxxx on string

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

Refresh token never returned after custom token generation.

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.

Fatal error when refresh token is experied

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.

It's not possible to override the default RefreshToken class

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>

Header based refreshToken

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.

Question: How to use this bundle [BestPractice]

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:

  1. the client does an api call with a JWTToken.
  2. the client needs to check if the call was valid. If it was invalid, due to an expired JWTToken, it has to save to somehow cache the request data, ask for a new JWTToken via the RefreshToken and then do the origin api call again.

In this scenario, the client contains to much intelligence. Did i miss something or got something completely wrong?

Kind regards
Max

How to set user_provider to Doctrine user provider?

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"

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

Add endpoint for clients who wants to revoke tokens

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.

Extra

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.

Add encoder for refresh_token

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

Multiple providers

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

refresh token with additional fields in payload

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?

refresh_token i am getting Forbidden 403

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

Allow distinct entity manager instead of default

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:

  • Allow in bundle config to change entity manager that will be injected to RefreshTokenManager service.

no new refresh token on credentials authentication

Scenario:

  1. Auth with credentials for user 1:
    token: abc
    refresh_token: xyz

  2. Get new token with refresh_token:
    token: def
    refresh_token: xyz

  3. token expired, auth with credentials for user 1:
    token: ghi
    refresh_token: xyz

  4. 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.

Symfony 3.0 compatibility

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?

What's happened if users swap their usernames ?

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.

Events to Customize Response Data?

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!

JWTRefreshTokenBundle change user_identity_field

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 ?

Error on Symfony 3.1

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   +

Installation issue with Mongodb

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.

Strategy to support Symfony 2.x and/or 3.x

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?

Remove FOSUserBundle dependency

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?

Custom Entity give error

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"]:

Generate refresh token inside a controller

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?

"code": 401, "message": "Invalid credentials"

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: parameters.yml }

- { resource: security.yml }
- { resource: services.yml }
- { resource: "@KasualJobsBundle/Resources/config/services.yml" }

Put parameters here that don't need to change on each machine where the app is deployed

http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration

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 Configuration

twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"

Doctrine Configuration

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 Configuration

swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }

lexik_jwt_authentication

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


To get started with security, check out the documentation:

http://symfony.com/doc/current/book/security.html

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 }


Security issue: Loadable users are always authenticated

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.

Refresh Token Unique and Secure

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?

Cannot use another table name

I have custom entity which extends from the RefreshToken class. When updating the schema, I get two tables: refresh_tokens and myname_refresh_tokens.

JWTRefreshTokenBundle usage of refresh token as a service Issue

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

Does not support multiple custom providers for SF4

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

Possible to Use Chained User 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.

/api/token/refresh doesn't update the expiration date

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.