vendor/trikoder/oauth2-bundle/DependencyInjection/Configuration.php line 88

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Trikoder\Bundle\OAuth2Bundle\DependencyInjection;
  4. use Defuse\Crypto\Key;
  5. use Symfony\Component\Config\Definition\Builder\NodeDefinition;
  6. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  7. use Symfony\Component\Config\Definition\ConfigurationInterface;
  8. use Trikoder\Bundle\OAuth2Bundle\OAuth2Grants;
  9. final class Configuration implements ConfigurationInterface
  10. {
  11. /**
  12. * {@inheritdoc}
  13. */
  14. public function getConfigTreeBuilder(): TreeBuilder
  15. {
  16. $treeBuilder = new TreeBuilder('trikoder_oauth2');
  17. $rootNode = $treeBuilder->getRootNode();
  18. $rootNode->append($this->createAuthorizationServerNode());
  19. $rootNode->append($this->createResourceServerNode());
  20. $rootNode->append($this->createScopesNode());
  21. $rootNode->append($this->createPersistenceNode());
  22. $rootNode
  23. ->children()
  24. ->scalarNode('exception_event_listener_priority')
  25. ->info('The priority of the event listener that converts an Exception to a Response.')
  26. ->defaultValue(10)
  27. ->end()
  28. ->scalarNode('role_prefix')
  29. ->info('Set a custom prefix that replaces the default "ROLE_OAUTH2_" role prefix.')
  30. ->defaultValue('ROLE_OAUTH2_')
  31. ->cannotBeEmpty()
  32. ->end()
  33. ->end();
  34. return $treeBuilder;
  35. }
  36. private function createAuthorizationServerNode(): NodeDefinition
  37. {
  38. $treeBuilder = new TreeBuilder('authorization_server');
  39. $node = $treeBuilder->getRootNode();
  40. $node
  41. ->isRequired()
  42. ->children()
  43. ->scalarNode('private_key')
  44. ->info("Full path to the private key file.\nHow to generate a private key: https://oauth2.thephpleague.com/installation/#generating-public-and-private-keys")
  45. ->example('/var/oauth/private.key')
  46. ->isRequired()
  47. ->cannotBeEmpty()
  48. ->end()
  49. ->scalarNode('private_key_passphrase')
  50. ->info('Passphrase of the private key, if any.')
  51. ->defaultValue(null)
  52. ->end()
  53. ->scalarNode('encryption_key')
  54. ->info(sprintf("The plain string or the ascii safe string used to create a %s to be used as an encryption key.\nHow to generate an encryption key: https://oauth2.thephpleague.com/installation/#string-password", Key::class))
  55. ->isRequired()
  56. ->cannotBeEmpty()
  57. ->end()
  58. ->enumNode('encryption_key_type')
  59. ->info('The type of value of "encryption_key".')
  60. ->values(['plain', 'defuse'])
  61. ->defaultValue('plain')
  62. ->end()
  63. ->scalarNode('access_token_ttl')
  64. ->info("How long the issued access token should be valid for, used as a default if there is no grant type specific value set.\nThe value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters")
  65. ->cannotBeEmpty()
  66. ->defaultValue('PT1H')
  67. ->end()
  68. ->scalarNode('refresh_token_ttl')
  69. ->info("How long the issued refresh token should be valid for, used as a default if there is no grant type specific value set.\nThe value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters")
  70. ->cannotBeEmpty()
  71. ->defaultValue('P1M')
  72. ->end()
  73. // @TODO Remove in v4 start
  74. ->scalarNode('auth_code_ttl')
  75. ->info("How long the issued authorization code should be valid for.\nThe value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters")
  76. ->cannotBeEmpty()
  77. ->setDeprecated('"%path%.%node%" is deprecated, use "%path%.grant_types.authorization_code.auth_code_ttl" instead.')
  78. ->beforeNormalization()
  79. ->ifNull()
  80. ->thenUnset()
  81. ->end()
  82. ->end()
  83. ->booleanNode('require_code_challenge_for_public_clients')
  84. ->info('Whether to require code challenge for public clients for the authorization code grant.')
  85. ->setDeprecated('"%path%.%node%" is deprecated, use "%path%.grant_types.authorization_code.require_code_challenge_for_public_clients" instead.')
  86. ->beforeNormalization()
  87. ->ifNull()
  88. ->thenUnset()
  89. ->end()
  90. ->end()
  91. ->end()
  92. ;
  93. foreach (OAuth2Grants::ALL as $grantType => $grantTypeName) {
  94. $oldGrantType = 'authorization_code' === $grantType ? 'auth_code' : $grantType;
  95. $node
  96. ->children()
  97. ->booleanNode(sprintf('enable_%s_grant', $oldGrantType))
  98. ->info(sprintf('Whether to enable the %s grant.', $grantTypeName))
  99. ->setDeprecated(sprintf('"%%path%%.%%node%%" is deprecated, use "%%path%%.grant_types.%s.enable" instead.', $grantType))
  100. ->beforeNormalization()
  101. ->ifNull()
  102. ->thenUnset()
  103. ->end()
  104. ->end()
  105. ->end()
  106. ;
  107. }
  108. // @TODO Remove in v4 end
  109. $node->append($this->createAuthorizationServerGrantTypesNode());
  110. $node
  111. ->validate()
  112. ->always(static function ($v): array {
  113. $grantTypesWithRefreshToken = array_flip(OAuth2Grants::WITH_REFRESH_TOKEN);
  114. foreach ($v['grant_types'] as $grantType => &$grantTypeConfig) {
  115. $grantTypeConfig['access_token_ttl'] = $grantTypeConfig['access_token_ttl'] ?? $v['access_token_ttl'];
  116. if (isset($grantTypesWithRefreshToken[$grantType])) {
  117. $grantTypeConfig['refresh_token_ttl'] = $grantTypeConfig['refresh_token_ttl'] ?? $v['refresh_token_ttl'];
  118. }
  119. // @TODO Remove in v4 start
  120. $oldGrantType = 'authorization_code' === $grantType ? 'auth_code' : $grantType;
  121. $grantTypeConfig['enable'] = $v[sprintf('enable_%s_grant', $oldGrantType)] ?? $grantTypeConfig['enable'];
  122. if ('authorization_code' === $grantType) {
  123. $grantTypeConfig['auth_code_ttl'] = $v['auth_code_ttl'] ?? $grantTypeConfig['auth_code_ttl'];
  124. $grantTypeConfig['require_code_challenge_for_public_clients'] = $v['require_code_challenge_for_public_clients']
  125. ?? $grantTypeConfig['require_code_challenge_for_public_clients'];
  126. }
  127. // @TODO Remove in v4 end
  128. }
  129. unset(
  130. $v['access_token_ttl'],
  131. $v['refresh_token_ttl'],
  132. // @TODO Remove in v4 start
  133. $v['enable_auth_code_grant'],
  134. $v['enable_client_credentials_grant'],
  135. $v['enable_implicit_grant'],
  136. $v['enable_password_grant'],
  137. $v['enable_refresh_token_grant'],
  138. $v['auth_code_ttl'],
  139. $v['require_code_challenge_for_public_clients']
  140. // @TODO Remove in v4 end
  141. );
  142. return $v;
  143. })
  144. ->end()
  145. ;
  146. return $node;
  147. }
  148. private function createAuthorizationServerGrantTypesNode(): NodeDefinition
  149. {
  150. $treeBuilder = new TreeBuilder('grant_types');
  151. $node = $treeBuilder->getRootNode();
  152. $node
  153. ->info('Enable and configure grant types.')
  154. ->addDefaultsIfNotSet()
  155. ;
  156. foreach (OAuth2Grants::ALL as $grantType => $grantTypeName) {
  157. $node
  158. ->children()
  159. ->arrayNode($grantType)
  160. ->addDefaultsIfNotSet()
  161. ->children()
  162. ->booleanNode('enable')
  163. ->info(sprintf('Whether to enable the %s grant.', $grantTypeName))
  164. ->defaultTrue()
  165. ->end()
  166. ->scalarNode('access_token_ttl')
  167. ->info(sprintf('How long the issued access token should be valid for the %s grant.', $grantTypeName))
  168. ->cannotBeEmpty()
  169. ->beforeNormalization()
  170. ->ifNull()
  171. ->thenUnset()
  172. ->end()
  173. ->end()
  174. ->end()
  175. ->end()
  176. ->end()
  177. ;
  178. }
  179. foreach (OAuth2Grants::WITH_REFRESH_TOKEN as $grantType) {
  180. $node
  181. ->find($grantType)
  182. ->children()
  183. ->scalarNode('refresh_token_ttl')
  184. ->info(sprintf('How long the issued refresh token should be valid for the %s grant.', OAuth2Grants::ALL[$grantType]))
  185. ->cannotBeEmpty()
  186. ->beforeNormalization()
  187. ->ifNull()
  188. ->thenUnset()
  189. ->end()
  190. ->end()
  191. ->end()
  192. ->end()
  193. ;
  194. }
  195. $node
  196. ->find('authorization_code')
  197. ->children()
  198. ->scalarNode('auth_code_ttl')
  199. ->info("How long the issued authorization code should be valid for.\nThe value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters")
  200. ->cannotBeEmpty()
  201. ->defaultValue('PT10M')
  202. ->end()
  203. ->booleanNode('require_code_challenge_for_public_clients')
  204. ->info('Whether to require code challenge for public clients for the authorization code grant.')
  205. ->defaultTrue()
  206. ->end()
  207. ->end()
  208. ->end()
  209. ;
  210. return $node;
  211. }
  212. private function createResourceServerNode(): NodeDefinition
  213. {
  214. $treeBuilder = new TreeBuilder('resource_server');
  215. $node = $treeBuilder->getRootNode();
  216. $node
  217. ->isRequired()
  218. ->children()
  219. ->scalarNode('public_key')
  220. ->info("Full path to the public key file.\nHow to generate a public key: https://oauth2.thephpleague.com/installation/#generating-public-and-private-keys")
  221. ->example('/var/oauth/public.key')
  222. ->isRequired()
  223. ->cannotBeEmpty()
  224. ->end()
  225. ->end()
  226. ;
  227. return $node;
  228. }
  229. private function createScopesNode(): NodeDefinition
  230. {
  231. $treeBuilder = new TreeBuilder('scopes');
  232. $node = $treeBuilder->getRootNode();
  233. $node
  234. ->info("Scopes that you wish to utilize in your application.\nThis should be a simple array of strings.")
  235. ->scalarPrototype()
  236. ->treatNullLike([])
  237. ;
  238. return $node;
  239. }
  240. private function createPersistenceNode(): NodeDefinition
  241. {
  242. $treeBuilder = new TreeBuilder('persistence');
  243. $node = $treeBuilder->getRootNode();
  244. $node
  245. ->info("Configures different persistence methods that can be used by the bundle for saving client and token data.\nOnly one persistence method can be configured at a time.")
  246. ->isRequired()
  247. ->performNoDeepMerging()
  248. ->children()
  249. // Doctrine persistence
  250. ->arrayNode('doctrine')
  251. ->children()
  252. ->scalarNode('entity_manager')
  253. ->info('Name of the entity manager that you wish to use for managing clients and tokens.')
  254. ->cannotBeEmpty()
  255. ->defaultValue('default')
  256. ->end()
  257. ->end()
  258. ->end()
  259. // In-memory persistence
  260. ->scalarNode('in_memory')
  261. ->end()
  262. ->end()
  263. ;
  264. return $node;
  265. }
  266. }