-
-
Notifications
You must be signed in to change notification settings - Fork 600
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unencrypted tokens and parser #822
Comments
What I'm kinda missing is what we're trying to achieve: what is the use-case, at high level/architecture? |
We have our own oauth2 server which uses the jwt tokens for access. Sometimes we need to decode it to check for a few things, including ids. This is only possible by using claims, which are not available on the |
Ah, so you mean that there should be a parser that guarantees that a non-encrypted token is returned. Perhaps it would be a good idea to have an |
I don't think it can always be assumed that a theoretically encrypted token could be decrypted without the use of a service with some configuration |
That would be a service :) |
Oh, sorry, I misread. |
@lcobucci WDYT? That would solve/remove the problem of casting a Lines 37 to 45 in 5f1fbfd
|
There are some oddities around, IMHO. I'm just dealing with creating tokens, so after reading the docs I wondered: How can they suggest calling So the only available builder is explicitly forced to return a So there is this unexplained gap, and having a dedicated method that explicitly returns |
Yes, that seems rather weird as well. I'd suggest just returning UnencryptedToken in both instances. |
It would be a separate object :) |
Folks, thanks for sharing your points!
The new interfaces were created in v4.0 and the token was designed to be just a value object - which is generally okay for an interface to depend on.
This is similar to the discussion in #814. I didn't have the time to finish that yet (which is why #814 is also lingering) but I'm documenting the To me, the The effort of implementing that kind of parser is really minimal: use Lcobucci\JWT\Encoding\JoseEncoder;
use Lcobucci\JWT\Token\Parser;
use Lcobucci\JWT\UnencryptedToken;
final class UnencryptedTokenParser implements \Lcobucci\JWT\Parser
{
private function __construct(private readonly \Lcobucci\JWT\Parser $parser) {}
public static function create(): self
{
return new self(new Parser(new JoseEncoder()));
}
public function parse(string $jwt): UnencryptedToken
{
$token = $this->parser->parse($jwt);
if (! $token instanceof UnencryptedToken) {
throw InvalidTokenStructure::tokenIsEncrypted();
}
return $token;
}
} My question is: is this really the direction we want to go? I kept this forward compatibility layer with the hope of supporting encryption without having to break BC (#6 is open for years and years). However, what I'm getting from users is: we don't really need encryption. If that's the case, we should aim at simplifying things (even if that would require a v5 soon - which is completely fine btw) instead of introducing more and more components. |
I'm not suggesting a new interface DecryptToken {
public function __invoke(Token $token): UnencryptedToken;
} This is kinda important due to parsing and decrypting being different planets 😁 |
If in 3 everything including claims was contained within the token itself I don't really see why the split was necessary between I don't really mind either solution, either merging interfaces or having a separate one. On that note, I wonder if using @lcobucci I don't really like the idea of changing the return type on an implementation itself since if you'd use something like symfony you could create a service and simply bind the interface as a service - you'd still get the same issue we're having right now, since the implementation itself is not important, the interface is. |
I have one thought related to the possible future situation with this library. You may remember when basically all JWT libraries had a serious security flaw because they unconditionally accepted "none" as the signature method announced in the header, so an attacker might just select that schema, omit the third part with the signature, and has full control over the data part and any claims. So now imagine that every user of this library is accustomed to "the parser returns The key learning from that security incident for me is: Ask for things very specifically, state what your expectations are in the code to allow detecting deviations early. This means that even if both types of token would be inheriting from the same parent interface, I'd still expect the parser to be asked to work on the two different things by calling two distinct methods. Maybe even have different parser implementations. What I'd avoid is to have one generic "parse it all" method that then has to use third party information, guesses or black magic about what type of token may have been passed. So if at all encrypted tokens would be implemented, they should be treated differently from the start, so any thoughts about maybe make them seem to just be |
My 2 cents. |
The point is differentiating JWE from the other tokens: no confusion between signing and encrypting. |
The library currently has No custom implementation, parse + decrypt, dependency injection, dummy implementation of validation rules, or any other complication should be necessary to do this. Higher level APIs that are either more flexible, more opinionated or different in any other way can coexist with this.
I agree with @SvenRtbg's argument, adding a specific parser would achieve that. |
Hi, first off, love the lib. It's even better in 4.x than it was in 3.x.
One thing bothers me a bit though, since the interfaces moved around and claims() got moved to the UnencryptedToken interface it left a weird gap in the Parser interface, since it's not possible to get a "proper" decoded token interface via the default implementation.
Yeah, it's returning an unencrypted plain token, but it's a bit weird that you can't simply force that.
I would like to propose a solution to this problem, just like there's a Token interface and UnencryptedToken interface, maybe let's have Parser and UencryptedParser interface? The default implementation could stay the same, the UnencryptedParser interface would simply add a new method -
parseUnencrypted(string $jwt): UnencryptedToken
or something like that.There'd be no modification required on the Parser class, simply changing the interface and having both methods return the same object.
The text was updated successfully, but these errors were encountered: