[Security] Access Token Authenticator#46428
[Security] Access Token Authenticator#46428chalasr merged 1 commit intosymfony:6.2from Spomky:features/access-token-authenticator
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 defaultYou 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
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.
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.
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.
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.
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.
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