diff --git a/security/access_token.rst b/security/access_token.rst index d5d607dbcb0..2e6438a633e 100644 --- a/security/access_token.rst +++ b/security/access_token.rst @@ -343,6 +343,443 @@ and configure the service ID as the ``success_handler``: ``failure_handler`` option and create a class that implements :class:`Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationFailureHandlerInterface`. +Using OpenID Connect (OIDC) +--------------------------- + +`OpenID Connect (OIDC)`_ is the third generation of OpenID technology and it's a RESTful HTTP API that uses +JSON as its data format. OpenID Connect is an authentication layer on top of the OAuth 2.0 authorization framework. +It allows to verify the identity of an end user based on the authentication performed by an authorization server. + +.. caution:: + + This feature is experimental and could change or be removed at any time without prior notice. + +1) Configure the OidcUserInfoTokenHandler +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 6.3 + + The ``OidcUserInfoTokenHandler`` class was introduced in Symfony 6.3. + +.. note:: + + The ``OidcUserInfoTokenHandler`` requires ``symfony/http-client`` package: + + .. code-block:: terminal + + $ composer require symfony/http-client + +Symfony provides a generic OidcUserInfoTokenHandler to call your OIDC server and retrieve the user info: + +.. configuration-block:: + + .. code-block:: yaml + + # config/packages/security.yaml + security: + firewalls: + main: + access_token: + token_handler: + oidc_user_info: + client: + base_uri: https://www.example.com/realms/demo/protocol/openid-connect/userinfo + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + .. code-block:: php + + // config/packages/security.php + use Symfony\Config\SecurityConfig; + + return static function (SecurityConfig $security) { + $security->firewall('main') + ->accessToken() + ->tokenHandler() + ->oidcUserInfo() + ->client() + ->baseUri('https://www.example.com/realms/demo/protocol/openid-connect/userinfo') + ; + }; + +.. tip:: + + Following the `OpenID Connect Specification`_, the `sub` claim + is used as user identifier by default. To use another claim, + specify it on the configuration: + +.. configuration-block:: + + .. code-block:: yaml + + # config/packages/security.yaml + security: + firewalls: + main: + access_token: + token_handler: + oidc_user_info: + claim: email + client: + base_uri: https://www.example.com/realms/demo/protocol/openid-connect/userinfo + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + .. code-block:: php + + // config/packages/security.php + use Symfony\Config\SecurityConfig; + + return static function (SecurityConfig $security) { + $security->firewall('main') + ->accessToken() + ->tokenHandler() + ->oidcUserInfo() + ->claim('email') + ->client() + ->baseUri('https://www.example.com/realms/demo/protocol/openid-connect/userinfo') + ; + }; + +.. tip:: + + The ``oidc_user_info`` token handler automatically creates + an HTTP client with the specified configuration. If you + prefer using your own client, you can specify the service + name via the ``client`` option: + +.. configuration-block:: + + .. code-block:: yaml + + # config/packages/security.yaml + security: + firewalls: + main: + access_token: + token_handler: + oidc_user_info: + client: oidc.client + + .. code-block:: xml + + + + + + + + + + + + + + + + + .. code-block:: php + + // config/packages/security.php + use Symfony\Config\SecurityConfig; + + return static function (SecurityConfig $security) { + $security->firewall('main') + ->accessToken() + ->tokenHandler() + ->oidcUserInfo() + ->client('oidc.client') + ; + }; + +By default, the ``OidcUserInfoTokenHandler`` creates an OidcUser with the claims. To create your own User from the +claims, you must :doc:`create your own UserProvider `:: + + // src/Security/Core/User/OidcUserProvider.php + use Symfony\Component\Security\Core\User\AttributesBasedUserProviderInterface; + + class OidcUserProvider implements AttributesBasedUserProviderInterface + { + public function loadUserByIdentifier(string $identifier, array $attributes = []): UserInterface + { + // do some magic + } + } + +2) Configure the OidcTokenHandler +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 6.3 + + The ``OidcTokenHandler`` class was introduced in Symfony 6.3. + +.. note:: + + The ``OidcTokenHandler`` requires ``web-token/jwt-signature``, ``web-token/jwt-checker`` and + ``web-token/jwt-signature-algorithm-ecdsa`` packages: + + .. code-block:: terminal + + $ composer require web-token/jwt-signature + $ composer require web-token/jwt-checker + $ composer require web-token/jwt-signature-algorithm-ecdsa + +Symfony provides a generic OidcTokenHandler to decode your token, validate it and retrieve the user info from it: + +.. configuration-block:: + + .. code-block:: yaml + + # config/packages/security.yaml + security: + firewalls: + main: + access_token: + token_handler: + oidc: + signature: + # Algorithm used to sign the JWS + algorithm: 'HS256' + # A JSON-encoded JWK + key: '{"kty":"...","k":"..."}' + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + .. code-block:: php + + // config/packages/security.php + use Symfony\Config\SecurityConfig; + + return static function (SecurityConfig $security) { + $security->firewall('main') + ->accessToken() + ->tokenHandler() + ->oidc() + ->signature() + ->algorithm('HS256') + ->key('{"kty":"...","k":"..."}') + ; + }; + +.. tip:: + + Following the `OpenID Connect Specification`_, the `sub` claim + is used by default as user identifier. To use another claim, + specify it on the configuration: + +.. configuration-block:: + + .. code-block:: yaml + + # config/packages/security.yaml + security: + firewalls: + main: + access_token: + token_handler: + oidc: + claim: email + signature: + algorithm: 'HS256' + key: '{"kty":"...","k":"..."}' + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + .. code-block:: php + + // config/packages/security.php + use Symfony\Config\SecurityConfig; + + return static function (SecurityConfig $security) { + $security->firewall('main') + ->accessToken() + ->tokenHandler() + ->oidc() + ->claim('email') + ->signature() + ->algorithm('HS256') + ->key('{"kty":"...","k":"..."}') + ; + }; + +.. tip:: + + The ``oidc`` token handler also check for the token audience. + By default, this audience is optional. To enable this check, + add the ``audience`` option: + +.. configuration-block:: + + .. code-block:: yaml + + # config/packages/security.yaml + security: + firewalls: + main: + access_token: + token_handler: + oidc: + audience: 'My audience' + signature: + algorithm: 'HS256' + key: '{"kty":"...","k":"..."}' + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + .. code-block:: php + + // config/packages/security.php + use Symfony\Config\SecurityConfig; + + return static function (SecurityConfig $security) { + $security->firewall('main') + ->accessToken() + ->tokenHandler() + ->oidc() + ->audience('My audience') + ->signature() + ->algorithm('HS256') + ->key('{"kty":"...","k":"..."}') + ; + }; + +By default, the OidcTokenHandler creates an OidcUser with the claims. To create your own User from the claims, +you must :doc:`create your own UserProvider `:: + + // src/Security/Core/User/OidcUserProvider.php + use Symfony\Component\Security\Core\User\AttributesBasedUserProviderInterface; + + class OidcUserProvider implements AttributesBasedUserProviderInterface + { + public function loadUserByIdentifier(string $identifier, array $attributes = []): UserInterface + { + // do some magic + } + } + .. _`JSON Web Tokens (JWT)`: https://datatracker.ietf.org/doc/html/rfc7519 .. _`SAML2 (XML structures)`: https://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html .. _`RFC6750`: https://datatracker.ietf.org/doc/html/rfc6750 +.. _`OpenID Connect Specification`: https://openid.net/specs/openid-connect-core-1_0.html +.. _`OpenID Connect (OIDC)`: https://en.wikipedia.org/wiki/OpenID#OpenID_Connect_(OIDC)