Storefront API security and authentication
Edit on GitHubSpryker Storefront API protects endpoints with the OAuth 2.0 protocol; for the authentication concept, token lifetimes, and error handling, see Authenticating and authorization. This document describes the Glue infrastructure implementation: the modules that provide authentication, user scopes, database tables, and extension points. The OAuth modules, scopes, and tokens described here are shared by both infrastructures; however, for endpoints served by API Platform, the code-level patterns differ—user access and endpoint protection are handled through security expressions and the ApiUser object, as described in API Platform security.
Authentication workflow:

Modules
Authentication and authorization are provided by the following modules:
| NAME | PURPOSE |
|---|---|
| league/oauth2-server | Third-party OAuth server, PhpLeague Oauth Server, integrated into Spryker |
| Oauth | Integrates PhpLeague Oauth Server with Spryker and also provides the necessary extension points. |
| OauthExtension | Provides extension point and plugin interfaces for the Oauth module. |
| OauthCustomerConnector | Provides authentication plugins for OAuth modules necessary to validate user credentials and scopes. |
| AuthRestApi | Provides authentication resources to the Storefront API. |
User scopes
The API has scopes defined for different groups of users. A scope defines, which resources specifically users can access.
By default, all Spryker customers are assigned to the customer scope.
To identify, which user has made a request, you can use the getRestUser() function of RestRequestInterface, for example:
class MyResourceHandler implements MyResourceInterface
/**
* @param \Spryker\Glue\GlueApplication\Rest\Request\Data\RestRequestInterface $restRequest
*
* @return \Generated\Shared\Transfer\CustomerTransfer
*/
protected function getCustomerTransfer(RestRequestInterface $restRequest): CustomerTransfer
{
return (new CustomerTransfer())->setCustomerReference($restRequest->getRestUser()->getNaturalIdentifier());
}
To identify the user, you can use the getSurrogateIdentifier and getNaturalIdentifier functions:
$restRequest->getRestUser()->getSurrogateIdentifier();
$restRequest->getRestUser()->getNaturalIdentifier();
Company user scope
In the B2B scenario, a user can be associated with an additional scope, company_user. This scope is added in the following cases:
- the user has impersonated as a Company User via the
/company-user-access-tokensendpoint; - the user is associated with a single Company User account;
- the user is associated with several Company User accounts and there is a default one.
Using this additional scope, you can perform additional checks to identify whether a resource should be available to a user. For this purpose, you can identify which Company User account is currently active, and also what company and business unit it belongs to. This can be done using the following helper methods:
$restRequest->getRestUser()->getIdCompanyUser();
$restRequest->getRestUser()->getIdCompanyBusinessUnit();
$restRequest->getRestUser()->getIdCompany();
B2B functionality is available in Spryker Storefront API since version 201907.0.
Endpoint protection
In addition to user scopes, each endpoint can be secured individually. For this purpose, you need to configure the routing of your Resource Feature Module. The Route Plugins of each module define which verbs are supported by the corresponding endpoint. This is done via the config function of the plugin class. The verbs are passed to it as a set of functions that should be called when the corresponding verb is passed.
For details, see Resource Routing.
For each function in the set, the second parameter determines, whether the corresponding verb requires authentication to use (the parameter value is true) or not (the value is false). If the parameter is not passed, the verb requires authentication.
In the following example, the PUT and DELETE verbs require authentication, and the GET verb can be called anonymously.
...
class MyResourceRoutePlugin extends AbstractPlugin implements ResourceRoutePluginInterface
{
public function configure(ResourceRouteCollectionInterface $resourceRouteCollection): ResourceRouteCollectionInterface
{
$resourceRouteCollection->addPost('post')
->addDelete('delete', true)
->addGet('get', false);
...
Database and extension points
All data related to API authentication functionality is stored in the following tables:
| TABLE | PURPOSE |
|---|---|
| spy_oauth_access_token | Stores all issued tokens. The table is not used for token verification, it’s added for audit purposes only. |
| spy_oauth_client | Contains a list of clients that are currently using OAuth, one record for each frontend customer. The is_confidental field identifies whether a specific client must provide a password. |
| spy_oauth_scope | Stores user scopes. |
The OAuth and OAuthExtension modules also provides the following extension points:
| EXTENSION POINT | METHOD | INTERFACE |
|---|---|---|
| User provider plugins | getUserProviderPlugins() |
\Spryker\Zed\OauthExtension\Dependency\Plugin\OauthUserProviderPluginInterface |
| Scope provider plugins | getScopeProviderPlugins() |
\Spryker\Zed\OauthExtension\Dependency\Plugin\OauthScopeProviderPluginInterface |
Thank you!
For submitting the form