-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Security] Add Bearer Authenticator #45844
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
Comments
+1 on my side. Having a support for Bearer tokens containing a JWT (similarly to the HTTP Basic support we already have) will be useful in a lot of contexts, even when not using OIDC. |
Keep in mind that JWT is only one way to implement bearer tokens. Adding this feature is fine as long as we remain open to different implementations. |
Also, question discussed with @dunglas and @chalasr: which data from the JWT should be send to the UserProvider? The To handle this case, a configuration key would allow to change which data will be sent to the UserProvider (default: |
I think it's a good idea to have such an authenticator. Would it be possible to allow overriding "who" decodes the JWT? For example provide a decoder service that can be decorated so that it is possible to use another library if it is needed. |
Yes! We are lacking a "simple" built-in token/bearer authenticator, so I would love to see this one :) Maybe we can use the same approach as form login: provide an
Agreed, something like All of this is just some ideas from me. Feel free to discuss them or ping for help (here or on Slack). |
As i really needed that kind of authenticator and didn't see any implementation proposition, here is mine : The Authenticatorclass BearerAuthenticator extends AbstractAuthenticator
An exemple of a TokenEncoderInterface@mahono feel free to create yours class JWTTokenEncoder implements TokenEncoderInterface
An exemple of a TokenExtractorTthe authenticator has a ChainTokenExtractor iterating over all extractors such as header, query parameter, body parameter (as suggested by @wouterj) class AuthorizationHeaderTokenExtractor implements TokenExtractorInterface
I will create a dedicated Symfony\Component\Security\Core\Authentication\Token\TokenInterface Any first opinion about this solution ? (Obviously it's not completely finished) |
Thanks for the examples. Actually, I've been working on something similar on API Platform here: api-platform/demo#265 and will open a PR on Symfony very soon. |
Putting my lexik/jwt-authentication-bundle maintainer's hat here as this is one of the bundle's main features. Let me start with some background: Why I didn't contribute anything in this regard: JWT creation and verification implies to rely on a third party library such as lcobucci/jwt (which is the default one in the lexik bundle), as suggested by this issue. Back to the current topic: This proposes to add a way to authenticate any kind of Bearer token in a generic way, without handling the token creation part.
The list is not exhaustive and I'm really not sold we will be able to provide something generic enough to cover everyone's use case. Moreover, the JWT library integration is a blocking concern to me. So what we could do is to let this responsibility to the developer, but then is it worth it at all? All in all, I'm not sure we should do this. We abandoned the idea of implementing 2FA in core for the very same reason in #28868 (comment): we already have a well-maintained bundle for this. And if lexik/jwt is not enough to handle e.g. keycloack tokens (in fact it is, the token verification part can be used solely, independently from the token creation part, and it's highly customizable thanks to a bunch of events and abstractions), writing a custom authenticator is probably easier than it is for Symfony to provide a flexible, generic enough authenticator. Also
This looks familiar :) https://github.com/lexik/LexikJWTAuthenticationBundle/blob/2.x/TokenExtractor/TokenExtractorInterface.php |
Thanks for your constructive feedback @chalasr. The JWT library concern and questions you provided are critical indeed, and I won't be able to handle all the use cases related to them just on my own. The problem revealed with this issue is that even if there are a lot of bundles implementing OAuth2 & OIDC, they are all related to non-API applications: they provide a redirect instead of a proper 401/403 HTTP response in the authenticator, they require Twig + form for authentication, etc. I didn't find a clean API compatible authenticator. I don't like the idea to let the developer write its own authenticator, as it's a security topic and could easily create a lot of security failures (especially with OAuth2 & OIDC). |
I see in the comments this issue is of interest to some people who already provide their own implementation, so here is the idea I had when I created this issue: #46429 |
Hi there, I saw this issue few days ago and today I decided to propose a PR. Somes uses cases:
For all this use cases, the approach is the same: the authenticator I propose just need a security:
firewalls:
main:
pattern: ^/
access_token:
token_handler: 'App\Security\AccessTokenHandler' With the listener system and the specific EDIT: Example of a fictive token handler. <?php
namespace App\Security;
use App\Repository\AccessTokenRepository;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Http\Authenticator\AccessTokenHandler as AccessTokenHandlerAliasInterface;
class AccessTokenHandler implements AccessTokenHandlerAliasInterface
{
public function __construct(private readonly AccessTokenRepository $repository)
{
}
public function getUserIdentifierFrom(string $token): string
{
$accessToken = $this->repository->findOneByValue($token);
if ($accessToken === null) {
throw new BadCredentialsException('Invalid credentials.');
}
return $accessToken->getUserId();
}
}
|
Thank you for rising this discussion.
I support your wiling to improve the situation, I think we can.
I see your point. But I would arg that anyway, most of the security concerns that come with these protocols are out of the scope of this feature as it does not aim to know about which flow is used, how tokens transit, where they are stored nor what data they contain. So actually, such an integration would reduce mistakes at the signature verification level only. Even just supporting JWT from unknown sources is not going to be easy given the vagueness of the JWT spec. That's why I think we would better provide a good extension point rather than trying to cover such a broad scope, so that one can build on it by implementing their own verification logic (in core, api-platform and auth-related community bundles/recipes). |
I agree. I like the approach from @Spomky with the token handler. Even if it requires a bit of code from the developer comparing to my approach, it looks like a good compromise between security failures and JWT concerns. If we agree with his approach, I would be happy to help on his PR :-) (I just think it misses a bit of RFC 6750) |
Many thanks @vincentchalamon. I think this PR is mature enough now so let me know if you see anything I missed. |
Description
I'm implementing an OIDC architecture in an API first project, and wanted to secure my API with an authenticator. I first took a look at bundles like hwi/oauth-bundle or knpuniversity/oauth2-client-bundle, but they're not adapted to an API as they provide bunch of features not needed in an API, and provides their own JWT generation and storage (e.g.: cookie).
I talked about it with @dunglas who shares the idea to implement a Bearer authenticator directly in the Symfony Security bundle. The idea behind this authenticator would be to retrieve the token from the
Authorization
header (prefixed withBearer
), and validate and decode it in a BearerToken using lcobucci/jwt.Example
Note: I'm not happy about the
signature
andkey
configuration keys, they should be renamedThe text was updated successfully, but these errors were encountered: