Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • SensioLabs Professional services to help you with Symfony
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by
  1. Home
  2. Documentation
  3. Security
  4. How to use Access Token Authentication

How to use Access Token Authentication

Edit this page

Access tokens or API tokens are commonly used as authentication mechanism in API contexts. The access token is a string, obtained during authentication (using the application or an authorization server). The access token's role is to verify the user identity and receive consent before the token is issued.

Access tokens can be of any kind, for instance opaque strings, JSON Web Tokens (JWT) or SAML2 (XML structures). Please refer to the RFC6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage for a detailed specification.

Using the Access Token Authenticator

This guide assumes you have setup security and have created a user object in your application. Follow the main security guide if this is not yet the case.

1) Configure the Access Token Authenticator

To use the access token authenticator, you must configure a token_handler. The token handler receives the token from the request and returns the correct user identifier. To get the user identifier, implementations may need to load and validate the token (e.g. revocation, expiration time, digital signature, etc.).

1
2
3
4
5
6
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler: App\Security\AccessTokenHandler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token token-handler="App\Security\AccessTokenHandler"/>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
// config/packages/security.php
use App\Security\AccessTokenHandler;
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security): void {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler(AccessTokenHandler::class)
    ;
};

This handler must implement AccessTokenHandlerInterface:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// src/Security/AccessTokenHandler.php
namespace App\Security;

use App\Repository\AccessTokenRepository;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Http\AccessToken\AccessTokenHandlerInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;

class AccessTokenHandler implements AccessTokenHandlerInterface
{
    public function __construct(
        private AccessTokenRepository $repository
    ) {
    }

    public function getUserBadgeFrom(string $accessToken): UserBadge
    {
        // e.g. query the "access token" database to search for this token
        $accessToken = $this->repository->findOneByValue($accessToken);
        if (null === $accessToken || !$accessToken->isValid()) {
            throw new BadCredentialsException('Invalid credentials.');
        }

        // and return a UserBadge object containing the user identifier from the found token
        // (this is the same identifier used in Security configuration; it can be an email,
        // a UUID, a username, a database ID, etc.)
        return new UserBadge($accessToken->getUserId());
    }
}

The access token authenticator will use the returned user identifier to load the user using the user provider.

Caution

It is important to check the token if is valid. For instance, the example above verifies whether the token has not expired. With self-contained access tokens such as JWT, the handler is required to verify the digital signature and understand all claims, especially sub, iat, nbf and exp.

2) Configure the Token Extractor (Optional)

The application is now ready to handle incoming tokens. A token extractor retrieves the token from the request (e.g. a header or request body).

By default, the access token is read from the request header parameter Authorization with the scheme Bearer (e.g. Authorization: Bearer the-token-value).

Symfony provides other extractors as per the RFC6750:

header (default)
The token is sent through the request header. Usually Authorization with the Bearer scheme.
query_string
The token is part of the request query string. Usually access_token.
request_body
The token is part of the request body during a POST request. Usually access_token.

Caution

Because of the security weaknesses associated with the URI method, including the high likelihood that the URL or the request body containing the access token will be logged, methods query_string and request_body SHOULD NOT be used unless it is impossible to transport the access token in the request header field.

You can also create a custom extractor. The class must implement AccessTokenExtractorInterface.

1
2
3
4
5
6
7
8
9
10
11
12
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler: App\Security\AccessTokenHandler

                # use a different built-in extractor
                token_extractors: request_body

                # or provide the service ID of a custom extractor
                token_extractors: 'App\Security\CustomTokenExtractor'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token token-handler="App\Security\AccessTokenHandler">
                <!-- use a different built-in extractor -->
                <token-extractor>request_body</token-extractor>

                <!-- or provide the service ID of a custom extractor -->
                <token-extractor>App\Security\CustomTokenExtractor</token-extractor>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// config/packages/security.php
use App\Security\AccessTokenHandler;
use App\Security\CustomTokenExtractor;
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security): void {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler(AccessTokenHandler::class)

            // use a different built-in extractor
            ->tokenExtractors('request_body')

            # or provide the service ID of a custom extractor
            ->tokenExtractors(CustomTokenExtractor::class)
    ;
};

It is possible to set multiple extractors. In this case, the order is important: the first in the list is called first.

1
2
3
4
5
6
7
8
9
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler: App\Security\AccessTokenHandler
                token_extractors:
                    - 'header'
                    - 'App\Security\CustomTokenExtractor'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token token-handler="App\Security\AccessTokenHandler">
                <token-extractor>header</token-extractor>
                <token-extractor>App\Security\CustomTokenExtractor</token-extractor>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// config/packages/security.php
use App\Security\AccessTokenHandler;
use App\Security\CustomTokenExtractor;
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security): void {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler(AccessTokenHandler::class)
            ->tokenExtractors([
                'header',
                CustomTokenExtractor::class,
            ])
    ;
};

3) Submit a Request

That's it! Your application can now authenticate incoming requests using an API token.

Using the default header extractor, you can test the feature by submitting a request like this:

1
2
$ curl -H 'Authorization: Bearer an-accepted-token-value' \
    https://localhost:8000/api/some-route

Customizing the Success Handler

By default, the request continues (e.g. the controller for the route is run). If you want to customize success handling, create your own success handler by creating a class that implements AuthenticationSuccessHandlerInterface and configure the service ID as the success_handler:

1
2
3
4
5
6
7
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler: App\Security\AccessTokenHandler
                success_handler: App\Security\Authentication\AuthenticationSuccessHandler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token token-handler="App\Security\AccessTokenHandler"
                success-handler="App\Security\Authentication\AuthenticationSuccessHandler"
            />
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
// config/packages/security.php
use App\Security\AccessTokenHandler;
use App\Security\Authentication\AuthenticationSuccessHandler;
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security): void {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler(AccessTokenHandler::class)
            ->successHandler(AuthenticationSuccessHandler::class)
    ;
};

Tip

If you want to customize the default failure handling, use the failure_handler option and create a class that implements 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.

1) Configure the OidcUserInfoTokenHandler

The OidcUserInfoTokenHandler requires the symfony/http-client package to make the needed HTTP requests. If you haven't installed it yet, run this command:

1
$ composer require symfony/http-client

Symfony provides a generic OidcUserInfoTokenHandler to call your OIDC server and retrieve the user info:

1
2
3
4
5
6
7
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler:
                    oidc_user_info: https://www.example.com/realms/demo/protocol/openid-connect/userinfo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token>
                <token-handler oidc-user-info="https://www.example.com/realms/demo/protocol/openid-connect/userinfo"/>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
// config/packages/security.php
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler()
                ->oidcUserInfo('https://www.example.com/realms/demo/protocol/openid-connect/userinfo')
    ;
};

Following the OpenID Connect Specification, the sub claim is used as user identifier by default. To use another claim, specify it on the configuration:

1
2
3
4
5
6
7
8
9
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler:
                    oidc_user_info:
                        claim: email
                        base_uri: https://www.example.com/realms/demo/protocol/openid-connect/userinfo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token>
                <token-handler>
                    <oidc-user-info claim="email" base-uri="https://www.example.com/realms/demo/protocol/openid-connect/userinfo"/>
                </token-handler>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
// config/packages/security.php
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler()
                ->oidcUserInfo()
                    ->claim('email')
                    ->baseUri('https://www.example.com/realms/demo/protocol/openid-connect/userinfo')
    ;
};

The oidc_user_info token handler automatically creates an HTTP client with the specified base_uri. If you prefer using your own client, you can specify the service name via the client option:

1
2
3
4
5
6
7
8
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler:
                    oidc_user_info:
                        client: oidc.client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token>
                <token-handler>
                    <oidc-user-info client="oidc.client"/>
                </token-handler>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
// 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 object from the claims, you must create your own UserProvider:

1
2
3
4
5
6
7
8
9
10
// 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
    {
        // implement your own logic to load and return the user object
    }
}

2) Configure the OidcTokenHandler

The OidcTokenHandler requires the web-token/jwt-library package. If you haven't installed it yet, run this command:

1
$ composer require web-token/jwt-library

Symfony provides a generic OidcTokenHandler to decode your token, validate it and retrieve the user info from it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler:
                    oidc:
                        # Algorithms used to sign the JWS
                        algorithms: ['ES256', 'RS256']
                        # A JSON-encoded JWK
                        keyset: '{"keys":[{"kty":"...","k":"..."}]}'
                        # Audience (`aud` claim): required for validation purpose
                        audience: 'api-example'
                        # Issuers (`iss` claim): required for validation purpose
                        issuers: ['https://oidc.example.com']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token>
                <token-handler>
                    <!-- Algorithm used to sign the JWS -->
                    <!-- A JSON-encoded JWK -->
                    <!-- Audience (`aud` claim): required for validation purpose -->
                    <oidc keyset="{'keys':[{'kty':'...','k':'...'}]}" audience="api-example">
                        <!-- Issuers (`iss` claim): required for validation purpose -->
                        <algorithm>ES256</algorithm>
                        <algorithm>RS256</algorithm>
                        <issuer>https://oidc.example.com</issuer>
                    </oidc>
                </token-handler>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// config/packages/security.php
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler()
                ->oidc()
                    // Algorithm used to sign the JWS
                    ->algorithms(['ES256', 'RS256'])
                    // A JSON-encoded JWK
                    ->keyset('{"keys":[{"kty":"...","k":"..."}]}')
                    // Audience (`aud` claim): required for validation purpose
                    ->audience('api-example')
                    // Issuers (`iss` claim): required for validation purpose
                    ->issuers(['https://oidc.example.com'])
    ;
};

7.1

The support of multiple algorithms to sign the JWS was introduced in Symfony 7.1. In previous versions, only the ES256 algorithm was supported.

Following the OpenID Connect Specification, the sub claim is used by default as user identifier. To use another claim, specify it on the configuration:

1
2
3
4
5
6
7
8
9
10
11
12
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler:
                    oidc:
                        claim: email
                        algorithms: ['ES256', 'RS256']
                        keyset: '{"keys":[{"kty":"...","k":"..."}]}'
                        audience: 'api-example'
                        issuers: ['https://oidc.example.com']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token>
                <token-handler>
                    <oidc claim="email" keyset="{'keys':[{'kty':'...','k':'...'}]}" audience="api-example">
                        <algorithm>ES256</algorithm>
                        <algorithm>RS256</algorithm>
                        <issuer>https://oidc.example.com</issuer>
                    </oidc>
                </token-handler>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// config/packages/security.php
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler()
                ->oidc()
                    ->claim('email')
                    ->algorithms(['ES256', 'RS256'])
                    ->keyset('{"keys":[{"kty":"...","k":"..."}]}')
                    ->audience('api-example')
                    ->issuers(['https://oidc.example.com'])
    ;
};

By default, the OidcTokenHandler creates an OidcUser with the claims. To create your own User from the claims, you must create your own UserProvider:

1
2
3
4
5
6
7
8
9
10
// 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
    {
        // implement your own logic to load and return the user object
    }
}

Using CAS 2.0

7.1

The support for CAS token handlers was introduced in Symfony 7.1.

Central Authentication Service (CAS) is an enterprise multilingual single sign-on solution and identity provider for the web and attempts to be a comprehensive platform for your authentication and authorization needs.

Configure the Cas2Handler

Symfony provides a generic Cas2Handler to call your CAS server. It requires the symfony/http-client package to make the needed HTTP requests. If you haven't installed it yet, run this command:

1
$ composer require symfony/http-client

You can configure a cas token handler as follows:

1
2
3
4
5
6
7
8
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler:
                    cas:
                        validation_url: https://www.example.com/cas/validate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token>
                <token-handler>
                    <cas validation-url="https://www.example.com/cas/validate"/>
                </token-handler>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
// config/packages/security.php
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler()
                ->cas()
                    ->validationUrl('https://www.example.com/cas/validate')
    ;
};

The cas token handler automatically creates an HTTP client to call the specified validation_url. If you prefer using your own client, you can specify the service name via the http_client option:

1
2
3
4
5
6
7
8
9
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler:
                    cas:
                        validation_url: https://www.example.com/cas/validate
                        http_client: cas.client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token>
                <token-handler>
                    <cas validation-url="https://www.example.com/cas/validate" http-client="cas.client"/>
                </token-handler>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
// config/packages/security.php
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler()
                ->cas()
                    ->validationUrl('https://www.example.com/cas/validate')
                    ->httpClient('cas.client')
    ;
};
By default the token handler will read the validation URL XML response with
cas prefix but you can configure another prefix:
1
2
3
4
5
6
7
8
9
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler:
                    cas:
                        validation_url: https://www.example.com/cas/validate
                        prefix: cas-example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
    xmlns:srv="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/security
        https://symfony.com/schema/dic/security/security-1.0.xsd">

    <config>
        <firewall name="main">
            <access-token>
                <token-handler>
                    <cas validation-url="https://www.example.com/cas/validate" prefix="cas-example"/>
                </token-handler>
            </access-token>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
// config/packages/security.php
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->accessToken()
            ->tokenHandler()
                ->cas()
                    ->validationUrl('https://www.example.com/cas/validate')
                    ->prefix('cas-example')
    ;
};

Creating Users from Token

Some types of tokens (for instance OIDC) contain all information required to create a user entity (e.g. username and roles). In this case, you don't need a user provider to create a user from the database:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// src/Security/AccessTokenHandler.php
namespace App\Security;

// ...
class AccessTokenHandler implements AccessTokenHandlerInterface
{
    // ...

    public function getUserBadgeFrom(string $accessToken): UserBadge
    {
        // get the data from the token
        $payload = ...;

        return new UserBadge(
            $payload->getUserId(),
            fn (string $userIdentifier) => new User($userIdentifier, $payload->getRoles())
        );
    }
}

When using this strategy, you can omit the user_provider configuration for stateless firewalls.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version

    Symfony 7.1 is backed by

    Become certified from home

    Become certified from home

    Be safe against critical risks to your projects and businesses

    Be safe against critical risks to your projects and businesses

    Version:

    Table of Contents

    • Using the Access Token Authenticator
      • 1) Configure the Access Token Authenticator
      • 2) Configure the Token Extractor (Optional)
      • 3) Submit a Request
    • Customizing the Success Handler
    • Using OpenID Connect (OIDC)
      • 1) Configure the OidcUserInfoTokenHandler
      • 2) Configure the OidcTokenHandler
    • Using CAS 2.0
      • Configure the Cas2Handler
    • Creating Users from Token

    Symfony footer

    Avatar of Takashi Kanemoto, a Symfony contributor

    Thanks Takashi Kanemoto (@ttskch) for being a Symfony contributor

    3 commits • 100 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • What is Symfony?
      • Symfony at a Glance
      • Symfony Components
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • Symfony Community
      • SymfonyConnect
      • Events & Meetups
      • Projects using Symfony
      • Contributors
      • Symfony Jobs
      • Backers
      • Code of Conduct
      • Downloads Stats
      • Support
    • Blog

      • All Blog Posts
      • A Week of Symfony
      • Case Studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Living on the edge
      • Releases
      • Security Advisories
      • Symfony Insight
      • Twig
      • SensioLabs Blog
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Powered by

    Follow Symfony