How to integrate API Platform Security
Edit on GitHubThis document describes how to integrate Symfony’s SecurityBundle with the API Platform to enable authentication and authorization for your API resources.
Prerequisites
- API Platform is already integrated as described in How to integrate API Platform.
- The
spryker/api-platformmodule version0.5.0or later is installed.
1. Register the SecurityBundle
Add SecurityBundle to the bundles.php file for each Glue application where you want to enable security.
For Glue application
config/Glue/bundles.php
<?php
declare(strict_types = 1);
use ApiPlatform\Symfony\Bundle\ApiPlatformBundle;
use Spryker\ApiPlatform\SprykerApiPlatformBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
return [
FrameworkBundle::class => ['all' => true],
SecurityBundle::class => ['all' => true],
TwigBundle::class => ['all' => true],
ApiPlatformBundle::class => ['all' => true],
SprykerApiPlatformBundle::class => ['all' => true],
];
For GlueStorefront application
config/GlueStorefront/bundles.php
<?php
declare(strict_types = 1);
use ApiPlatform\Symfony\Bundle\ApiPlatformBundle;
use Spryker\ApiPlatform\SprykerApiPlatformBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
return [
FrameworkBundle::class => ['all' => true],
SecurityBundle::class => ['all' => true],
TwigBundle::class => ['all' => true],
ApiPlatformBundle::class => ['all' => true],
SprykerApiPlatformBundle::class => ['all' => true],
];
For GlueBackend application
config/GlueBackend/bundles.php
<?php
declare(strict_types = 1);
use ApiPlatform\Symfony\Bundle\ApiPlatformBundle;
use Spryker\ApiPlatform\SprykerApiPlatformBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
return [
FrameworkBundle::class => ['all' => true],
SecurityBundle::class => ['all' => true],
TwigBundle::class => ['all' => true],
ApiPlatformBundle::class => ['all' => true],
SprykerApiPlatformBundle::class => ['all' => true],
];
SecurityBundle must be registered before ApiPlatformBundle and SprykerApiPlatformBundle so that the security services are available when API Platform compiles its configuration.
2. Configure the security firewall
Create a security.php configuration file for each Glue application. This file defines the authentication provider, firewall, and default access control.
For Glue application
config/Glue/packages/security.php
<?php
declare(strict_types=1);
use Spryker\ApiPlatform\Security\ApiUserProvider;
use Spryker\ApiPlatform\Security\OauthAuthenticator;
use Symfony\Config\SecurityConfig;
return static function (SecurityConfig $security): void {
$security->provider('api_oauth_provider')
->id(ApiUserProvider::class);
$security->firewall('main')
->lazy(true)
->stateless(true)
->provider('api_oauth_provider')
->customAuthenticators([OauthAuthenticator::class]);
// Public by default - individual resources use security expressions for authorization
$security->accessControl()
->path('^/')
->roles(['PUBLIC_ACCESS']);
};
For GlueStorefront application
config/GlueStorefront/packages/security.php
Use the same configuration as above.
For GlueBackend application
config/GlueBackend/packages/security.php
Use the same configuration as above.
Configuration explained
| Setting | Description |
|---|---|
provider('api_oauth_provider') |
Registers the user provider that builds ApiUser objects from validated JWT claims. |
firewall('main')->lazy(true) |
The authenticator is only instantiated when a route requires authentication, reducing overhead for public endpoints. |
firewall('main')->stateless(true) |
Disables session-based authentication. Every request must include its own Bearer token. |
customAuthenticators([OauthAuthenticator::class]) |
Registers the Spryker OAuth authenticator that validates Bearer tokens using the local OAuth infrastructure. |
accessControl()->roles(['PUBLIC_ACCESS']) |
Grants public access to all paths by default. Individual resources opt in to authentication using security expressions. |
3. Add security expressions to resources
After the SecurityBundle is configured, you can protect resources using security expressions in your YAML resource schemas.
Protect an entire resource
resource:
name: Customers
shortName: customers
security: "is_granted('ROLE_USER')"
operations:
- type: Get
- type: Patch
- type: Delete
Protect specific operations
resource:
name: Customers
shortName: customers
operations:
- type: Post
# Public — allows registration without authentication
- type: Get
security: "is_granted('ROLE_USER')"
- type: Patch
security: "is_granted('ROLE_USER')"
Regenerate resources
After adding security expressions, regenerate your API resources:
docker/sdk cli glue api:generate
4. Clear caches
Clear application caches after configuration changes:
docker/sdk cli console cache:clear
Verification
Verify SecurityBundle is registered
Check that the security services are available:
docker/sdk cli glue debug:container SecurityBundle
Test authentication
Send a request without a token to a protected resource — it should return 401 Unauthorized:
curl -s https://glue-storefront.your-domain/customers/DE--1 | jq .
Send a request with a valid Bearer token:
curl -s -H "Authorization: Bearer <your-jwt-token>" \
https://glue-storefront.your-domain/customers/DE--1 | jq .
Compile-time validation
If you add security expressions to resource schemas but forget to register the SecurityBundle, the application throws an error at compile time:
InvalidArgumentException: The SecurityBundle is not registered but security expressions
were found in the following resources: [customers, orders]. Register the SecurityBundle
in config/{Application}/bundles.php.
This validation is performed by the SecurityServiceRegistrationPass compiler pass.
Next steps
- Security - Understanding authentication and authorization
- Resource Schemas - Security expression syntax
- API Platform Configuration - Configuration options
Thank you!
For submitting the form