LexikJWTAuthenticationBundle icon indicating copy to clipboard operation
LexikJWTAuthenticationBundle copied to clipboard

Question: Database-less user: initial token creation...

Open akomm opened this issue 7 years ago • 2 comments

This documentations explains everything, but as soon as it comes to how you actually initially create a token from a given source, e. G. database, it just makes a cut.

I understand JWT and I wanted to go the db-less way. Your db-less provider part is clear. From my sy security understand I have an idea how I could create the token: Just use an entity provider for the login firewall and the JWT provider for the token (some "cons" coming).

I also have to use two different "user" types. One as entity for login API and one as JWT db-less user, for the token authenticated API. This is because the username property is part of the JwtUser type and has no mapping information, I would have to override its private property to add mapping and I would carry over API my entity User does not need. Making two unrelated classes on the other hand makes it kind of smell in my opinion.

But because the docs either hide it impossible or it just miss any hints regarding the actual initial token creation, I'm not sure whether the above approach is the intended way to do it or not.

The whole documentation seem to have "holes" whenever it comes to the initial token creation (otherwise its very good!). It feels like "1. collection underparts 2. ??? 3. profit". Even the "getting started/usage" gives some configuration and then proposes to check using curl, while the result on given conditions would be always a 401.

edit Hm. Going to try implementing JwtUserInterface instead of extending JwtUser, lets see if that works out.

edit2

My current solution, with two User types, matching in the UserInterface interface from symfony security component:

security:
  providers:
    jwt:
      lexik_jwt:
        class: AppBundle\Security\JwtUser
    db:
      entity:
        class: AppBundle\Entity\User
        property: username

  encoders:
    AppBundle\Entity\User: bcrypt

  firewalls:
    dev:
      pattern: ^/(_(profiler|wdt)|css|images|js)/
      security: false

    login:
      pattern:  ^/api/login
      stateless: true
      anonymous: true
      provider: db
      form_login:
        check_path:               /api/login_check
        success_handler:          lexik_jwt_authentication.handler.authentication_success
        failure_handler:          lexik_jwt_authentication.handler.authentication_failure
        require_previous_session: false

    api:
      pattern:   ^/graphql
      stateless: true
      provider:  jwt
      guard:
        authenticators:
          - lexik_jwt_authentication.jwt_token_authenticator

  access_control:
    - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/graphql,   roles: IS_AUTHENTICATED_FULLY }

The Entity user is only used on login. Rest works with JwtUser

akomm avatar Sep 01 '17 10:09 akomm

First, thank you very much for your feedback.

Your use case is interesting. Actually, I think I would solve it the same you did it, even if I don't know the details of your implementation (did you finally stop extending JWTUser? If yes, could you tell me why?).

The JWTUserProvider is a very recent feature. I must admit that I did not implement it from scratch with concrete enough use case yet, I'm sure you are right about the lack of doc and the fact if feels like "what happen once configured? what ends up in my token? how is it verified?". This issue is a great reminder, we must be very explicit about the features this bundle provides, and gives very detailed examples.

Even the "getting started/usage" gives some configuration and then proposes to check using curl, while the result on given conditions would be always a 401.

That's weird! I have to retry it and patch it if needed, but right now I don't see what are the conditions you are referring to which could cause it to fail.

Making two unrelated classes on the other hand makes it kind of smell in my opinion.

I will take time to look at this, and hopefully propose you some solutions to improve the situation.

chalasr avatar Sep 06 '17 19:09 chalasr

That's weird! I have to retry it and patch it if needed, but right now I don't see what are the conditions you are referring to which could cause it to fail.

No provider configuration: Configuration Followed by: Usage

Configuration lacks any note about provider, which is required for the curl call in "Usage" to ever return a token and being a real verification.

I understand that this bundle does not care about the provider, which is good. It can work with any compatible with the provider interface. The problem is, that for someone who does not know the implementation of this bundle, it is not clear whether to use the regular configuration from symfony/security for this or some higher order configuration provided by the extension's configuration. Because when something that is required in the configuration (provider), is missing, one actually assumes a purpose in its absence. So there must be another way to do it? Or not?

The major, important thing in general is often a small note to clarify whether you do something the "regular" way or this project gives some higher order configuration you should rather use.

DB-less user:

Yes, you can create the user from token payload provided from client & verified using key. But who or what did initially create the token? I understand that the issuer could be anything, that is trusted by having the proper key to sign it. It could be even another app! The problem is, that the purpose of this feature is not entirely clear. I can only guess. Maybe it is only intended for token verification which are not created by the App itself (external)? Or the docs just miss some info as how to initial create the token to later verify it and build user without database query. Here I end up in the same question, as in the configuration/usage part.

The JWTUserProvider is a very recent feature. I must admit that I did not implement it from scratch with concrete enough use case yet, I'm sure you are right about the lack of doc and the fact if feels like "what happen once configured? what ends up in my token? how is it verified?".

what ends up in my token Well in my opinion it is explained well. Even how you can modify it! :+1:

how is it verified While it is sure nice to note, it is part of the JWT spec and more generally asymetric encryption. I would not expect it to be the responsibility for it to be explained here, but it would also not harm if there would be a note. In my case I started using this bundle after I was clear about how JWT works and about the concept, so it never was a question for me.

akomm avatar Sep 07 '17 13:09 akomm