2. Bundle config
All bundle settings are located in the file config/packages/ufo_json_rpc.yaml.
It is possible to configure the API security parameters and some data format parameters returned in the documentation request.
Block security
Currently, the only mechanism for protecting access to your API is to set up an access key check (api_token).
Parameters protected_api and protected_doc (boolean)
These parameters indicate whether the API methods and documentation should be protected, respectively.
By default, API methods are protected, and the documentation is open.
2
3
4
security:
protected_api: true # Protection API requests
protected_doc: false # Protection API documentation
protected_api, you need to configure the tokens that will provide access.
If you protect your API throughFirst, you need to decide on the token name.
Parameter token_name
The RpcSecurity component will look for a specific key in the request headers that you can set in the package settings. The default value is token_name: 'Ufo-RPC-Token'. You can set any other value that meets the following requirements.
HTTP Header Naming Requirements
Parameter clients_tokens
Next, specify an array of client tokens that will have access to the API.
There is some variability here.
Tokens in parameters
You can hardcode tokens directly into the settings file.
This is bad from a security standpoint because if the code is stored in a public repository, anyone will have access to this token.
2
3
4
5
security:
token_name: 'Ufo-RPC-Token'
clients_tokens:
- 'ClientTokenExample' # hardcoded token example. Importantly!!! Replace or delete it!
Tokens in environment variables
This is the most appropriate mechanism if you are developing a service for a distributed backend written in SOA (Service-Oriented Architecture). Typically, in this case, you need to open access to the API for one or a limited number of client applications, and key updates will not occur too often.
In this case, you can specify tokens in environment variables (file .env.local during local development). This mechanism is secure enough in terms of access storage.
2
TOKEN_FOR_APP_2=456fg87g8h98jmnb8675r4445n8up365
2
3
4
5
6
security:
token_key_in_header: 'Ufo-RPC-Token'
clients_tokens:
- '%env(resolve:TOKEN_FOR_APP_1)%' # token example from .env.local
- '%env(resolve:TOKEN_FOR_APP_2)%' # token example from .env.local
User Tokens
Suppose you need to create personal keys for your application users, perhaps you want to implement limits or other restrictions.
In this case, you do not need to specify the list of tokens in the configs; you can store them in a database or elsewhere according to your business logic. The only requirement is that you must have a service that can check whether the provided token exists.
To enable the JsonRpcServer to use your logic, you need to implement a custom class that implements the interface Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator
Example of a custom token validator
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
namespace App\Services\RpcSecurity;
use App\Services\UserService;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator;
use Ufo\RpcError\RpcInvalidTokenException;
class UserTokenValidator implements ITokenValidator
{
public function __construct(protected UserService $userService) {}
public function isValid(string $token): true
{
try {
$this->userService->getUserByToken($token);
return true;
} catch (UserNotFoundException $e) {
throw new RpcInvalidTokenException(previous: $e);
}
}
}
Next, you need to specify in the config/services.yaml file that classes depending on the ITokenValidator interface should accept your new class.
2
3
4
5
6
7
8
9
10
# some parameters list
# ...
services:
# some services list
# ...
Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator:
class: App\Services\RpcSecurity\UserTokenValidator
Block async
This block is for configuring asynchronous transport.
Add the parameter rpc_async, which contains a DSN format string. This string is a configuration for Symfony Messenger, indicating the asynchronous transport on which the RPC Server will await incoming requests if you have a consumer running (php bin/console messenger:consume rpc_async). For a detailed understanding of this process, read the Symfony Messenger documentation.
2
3
4
async:
rpc_async: '%env(resolve:RPC_TRANSPORT_DSN)%'
Block docs
This block configures some parameters for generating documentation when you make a GET request to the RPC Server.
- project_name: The project name displayed in the documentation
- project_description: The project description
- project_version: The current version of your API
- async_dsn_info: Indicates whether to display information about asynchronous transport in the documentation
- validations.symfony_asserts: <bool> Indicates whether to display the validation constraint string for the parameter (if you use validation)
2
3
4
5
6
7
8
9
10
docs:
project_name: 'My Project'
project_description: 'My project description'
project_version: '1.0'
# Optional response details
async_dsn_info: false # Provide information about API that work asynchronously
validations:
symfony_asserts: false # Indicates if an array of Symfony validation constraints is used
Documentation Example
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
"openrpc":"1.2.6",
"info":{
"title":"My Project",
"description":"My project description",
"contact":{
"name":"ufo-tech/json-rpc-bundle",
"url":"https://docs.ufo-tech.space/bin/view/docs/JsonRpcBundle/?language=en"
},
"license":{
"name":"MIT"
},
"version":"1.0"
},
"servers":[
{
"url":"https://mysite.com/api",
"description":"Json-RPC api server from UFO Tec\n\nUFO Tech, or Universal Flexible Open Technologies, is an initiative aimed at providing PHP developers with tools to create complex yet user-friendly solutions for modern web applications and service-oriented architectures.",
"name":"UFO Json-RPC Server v.7.0.0",
"x-method":"POST",
"x-ufo":{
"envelop":"JSON-RPC-2.0/UFO-RPC-7.0.0",
"transport":{
"sync":{
"scheme":"https",
"host":"mysite.com",
"path":"/api",
"method":"POST"
},
"async":{
"scheme":"amqp",
"user":"{user}",
"pass":"{pass}",
"host":"mysite.com",
"port":5672,
"path":"/%2f/json-rpc"
}
},
"documentation":{
"json-rpc":"https://www.jsonrpc.org/specification",
"ufo-tech/json-rpc-bundle":"https://docs.ufo-tech.space/bin/view/docs/JsonRpcBundle/?language=en"
}
}
}
],
"methods":[
{
"name":"getUserNameByUuid",
"tags":[
{
"name":"App\\Api\\UserApiService"
}
],
"summary":"Get username by id",
"params":[
{
"name":"userId",
"description":"User Id format uuid",
"required":true,
"schema":{
"type":"string"
},
"x-ufo-assertions": "new Assert\\Uuid()"
}
],
"result":{
"name":"string",
"description":"User Name",
"schema":{
"type":"string"
}
}
}
]
}