-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Security] Access Token Authenticator #46428
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
[Security] Access Token Authenticator #46428
Conversation
I like this approach. |
|
Thanks for checking all tests! (btw, I'll look at the PR somewhere after 6.1 is released)
We'll ignore it for this PR (but if you want, a separate PR with a fix is always welcome 😉 )
See https://symfony.com/doc/current/contributing/code/pull_requests.html#automated-tests You must update the minimum versions in e.g. the SecurityBundle. |
src/Symfony/Bundle/SecurityBundle/Resources/config/security_authenticator.php
Outdated
Show resolved
Hide resolved
...e/SecurityBundle/Tests/DependencyInjection/Security/Factory/HeaderAccessTokenFactoryTest.php
Outdated
Show resolved
Hide resolved
...dle/SecurityBundle/Tests/DependencyInjection/Security/Factory/BodyAccessTokenFactoryTest.php
Outdated
Show resolved
Hide resolved
...le/SecurityBundle/Tests/DependencyInjection/Security/Factory/QueryAccessTokenFactoryTest.php
Outdated
Show resolved
Hide resolved
...dle/SecurityBundle/Tests/DependencyInjection/Security/Factory/BodyAccessTokenFactoryTest.php
Outdated
Show resolved
Hide resolved
...le/SecurityBundle/Tests/DependencyInjection/Security/Factory/QueryAccessTokenFactoryTest.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AbstractAccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/BodyAccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/QueryAccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
Hi, Many thanks for your comments. security:
firewalls:
main:
pattern: ^/
access_token:
token_handler: access_token.access_token_handler
# token_extractors:
# header: 'security.access_token_extractor.header' # This extrator is set by default You can add any extractor you want. Three already exist:
You can create as many extractors you need. They shall implement Other parameters are also present: security:
firewalls:
main:
pattern: ^/
access_token:
token_handler: access_token.access_token_handler
success_handler: access_token.success_handler
failure_handler: access_token.failure_handler
user_provider: 'another.user_provider'
token_extractors:
- 'security.access_token_extractor.header'
- 'security.access_token_extractor.query_string'
- 'security.access_token_extractor.request_body'
- 'App\Security\CustomExtractor' I have not created Exceptions. I revised my mind as the existing ones seem sufficient. Best regards. |
src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AccessTokenFactory.php
Show resolved
Hide resolved
src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AccessTokenFactory.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenHandlerInterface.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/BodyAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/BodyAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/BodyAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/HeaderAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/QueryAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your PR. In this review, I focussed mainly on code style and best practises. I'll do a more in-depth review later.
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/HeaderAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/QueryAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
...ymfony/Component/Security/Http/Authenticator/Passport/Credentials/AccessTokenCredentials.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Tests/Authenticator/BodyAccessTokenAuthenticatorTest.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Core/Authentication/Token/AccessToken.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/BodyAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
...ny/Component/Security/Http/Authenticator/AccessToken/DefaultAuthenticationFailureHandler.php
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very cool. Thanks for taking on this adventure @Spomky! (and wow, never knew this would be your first code contribution to Symfony core)
I've reviewed the component part for now. I really like how this PR is strict enough to completely follow the RFC, but yet keep enough open to be useful for many custom-build API authenticators.
src/Symfony/Component/Security/Core/Authentication/Token/AccessToken.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenExtractorInterface.php
Outdated
Show resolved
Hide resolved
...ny/Component/Security/Http/Authenticator/AccessToken/DefaultAuthenticationFailureHandler.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/BodyAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/BodyAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
...ymfony/Component/Security/Http/Authenticator/Passport/Credentials/AccessTokenCredentials.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessToken/HeaderAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
Hi all, Would you mind to review the changes I made and if the comments you raised have correctly been addressed? Many thanks. |
@Spomky if you click on the "load more ...", you'll see a review from me. I guess GitHub immediately hid it, so it got lost 🙂 |
src/Symfony/Component/Security/Http/AccessToken/HeaderAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AccessTokenFactory.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AccessTokenFactory.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AccessTokenFactory.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/AccessToken/AccessTokenHandlerInterface.php
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/AccessToken/FormEncodedBodyExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/AccessToken/QueryAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
...ymfony/Component/Security/Http/Authenticator/Passport/Credentials/AccessTokenCredentials.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
Super feature 👍🏼 Thanks for the work 👏🏼 . I let some comments |
Many thanks for the review and comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments about the CS, but I'm OK with the global design 👍🏼
public function __construct(private readonly string $parameter = 'access_token') | ||
{ | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't always use the same CS. This one ⬆️ VS
public function __construct(
private readonly iterable $accessTokenExtractors,
) {
}
In my applications (at work), I use the latest: more scalable, and reduce the diff when adding a new param.
However, I don't know what's the standard in Symfony (cc @nicolas-grekas @fabpot)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran php-cs-fixer but many files got updated. I just focussed on the one from this PR but the gaps you spotted were not found by the tool.
Anyway, I updated them to be consistent.
src/Symfony/Component/Security/Http/AccessToken/HeaderAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/AccessToken/RFC6750AuthenticationFailureHandler.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/AccessToken/RFC6750AuthenticationFailureHandler.php
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi there! I finally got the chance to review this a bit more in-depth and I'm really liking the feature :)
I've pushed 2 commits to your branch that fix the last 2 big remaining comments. It would be nice if you could squash all your commits into one and after that, it's ready to be merged in my opinion.
Thanks a lot for all the work!
src/Symfony/Component/Security/Http/AccessToken/FormEncodedBodyExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/AccessToken/QueryAccessTokenExtractor.php
Outdated
Show resolved
Hide resolved
Excellent! Many thanks to you and all the other reviewers. |
src/Symfony/Component/Security/Http/AccessToken/AccessTokenHandlerInterface.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php
Show resolved
Hide resolved
src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php
Outdated
Show resolved
Hide resolved
Thank you @Spomky. |
So cool! Many thanks for merging this PR. |
Awesome! 🚀 |
This PR was merged into the 6.2 branch. Discussion ---------- [Security] Access Tokens Documentation page related to the PR symfony/symfony#46428 Commits ------- f3f47ad Update docs for 6.2.0-RC1 changes to TokenHandlerInterface b65c136 Finish the docs for the new Access token authenticator 600bb80 Access Token Documentation
@Spomky Question regarding the configuration of this feature: why adding |
@vincentchalamon this allows setting a specific user provider for this firewall. If not set, the default user provider is used. |
See #48385 |
…vincentchalamon) This PR was squashed before being merged into the 6.3 branch. Discussion ---------- [Security] Add OidcUserInfoTokenHandler and OidcUser | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | N/A | License | MIT | Doc PR | symfony/symfony-docs#17463 Hi, This PR aims to complete [the previous one](#46428) from `@Spomky` with an AccessTokenHandler ready-to-use with an OIDC server (Keycloak, Auth0). ## TODO - [x] Rebase from 6.3 - [x] Rebase from #48285 - [x] Rebase from #48594 - [x] Write doc (symfony/symfony-docs#17463) - [x] Add TokenHandlerFactory - [x] Add ServiceTokenHandlerFactory for BC layer - [x] Add OidcUserInfoTokenHandlerFactory - [x] Add OidcTokenHandlerFactory (using web-token/jwt-*) - [x] Implement OidcUser to keep user claims from OIDC server - [x] Update doc PR about claims usage in a custom UserProvider - [x] ~Update doc PR about OidcUserProvider usage~ (abandonned) ## Usage ```yaml # usage with a custom client security: firewalls: main: pattern: ^/ access_token: token_handler: oidc_user_info: client: oidc.client ``` ```yaml # usage with generic HttpClient security: firewalls: main: pattern: ^/ access_token: token_handler: oidc_user_info: claim: email client: base_uri: https://www.example.com/realms/demo/protocol/openid-connect/userinfo ``` ```yaml # usage with token decode (no call to OIDC server) security: firewalls: main: pattern: ^/ access_token: token_handler: oidc: signature: # Algorithm used to sign the JWS algorithm: 'HS256' # A JSON-encoded JWK key: '{"kty":"...","k":"..."}' ``` ```php # usage with a custom UserProvider class CustomUserProvider implements UserProviderInterface { public function loadUserByIdentifier(string $identifier, array $claims = []): UserInterface { // do some magic } } ``` Commits ------- 99a35f0 [Security] Add OidcUserInfoTokenHandler and OidcUser
…vincentchalamon) This PR was squashed before being merged into the 6.3 branch. Discussion ---------- [Security] Add OidcUserInfoTokenHandler and OidcUser | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | N/A | License | MIT | Doc PR | symfony/symfony-docs#17463 Hi, This PR aims to complete [the previous one](symfony/symfony#46428) from `@Spomky` with an AccessTokenHandler ready-to-use with an OIDC server (Keycloak, Auth0). ## TODO - [x] Rebase from 6.3 - [x] Rebase from #48285 - [x] Rebase from #48594 - [x] Write doc (symfony/symfony-docs#17463) - [x] Add TokenHandlerFactory - [x] Add ServiceTokenHandlerFactory for BC layer - [x] Add OidcUserInfoTokenHandlerFactory - [x] Add OidcTokenHandlerFactory (using web-token/jwt-*) - [x] Implement OidcUser to keep user claims from OIDC server - [x] Update doc PR about claims usage in a custom UserProvider - [x] ~Update doc PR about OidcUserProvider usage~ (abandonned) ## Usage ```yaml # usage with a custom client security: firewalls: main: pattern: ^/ access_token: token_handler: oidc_user_info: client: oidc.client ``` ```yaml # usage with generic HttpClient security: firewalls: main: pattern: ^/ access_token: token_handler: oidc_user_info: claim: email client: base_uri: https://www.example.com/realms/demo/protocol/openid-connect/userinfo ``` ```yaml # usage with token decode (no call to OIDC server) security: firewalls: main: pattern: ^/ access_token: token_handler: oidc: signature: # Algorithm used to sign the JWS algorithm: 'HS256' # A JSON-encoded JWK key: '{"kty":"...","k":"..."}' ``` ```php # usage with a custom UserProvider class CustomUserProvider implements UserProviderInterface { public function loadUserByIdentifier(string $identifier, array $claims = []): UserInterface { // do some magic } } ``` Commits ------- 99a35f0fc3 [Security] Add OidcUserInfoTokenHandler and OidcUser
Hi,
This PR aims at fixing #45844.
It adds a new authenticator that is able to fetch a token in the request header and retrieve the associated user identifier.
The authenticator delegates the token loading to a handler. This handler could manage opaque tokens (random strings stored in a database) or self-contained tokens such as JWT, Paseto, SAML...
Firewall Configuration
This PR adds a new authenticator that covers the RFC6750:
access_token
.Also, it adds the possibility to extract the token from anywhere in the request.
Basic Configuration
Complete Configuration
Token Handler
This authenticator relies on a Token Handler. Its responsability is to
Tokens could be of any kind: opaque strings or self-contained tokens such as JWT, Paseto, SAML2...
Example: from a repository
Example: from a JWT