mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-08-01 06:01:42 +00:00
Started implementing an Oauth server
This commit is contained in:
parent
51ce453d1a
commit
c2948f7d84
31 changed files with 2551 additions and 90 deletions
|
|
@ -35,4 +35,5 @@ return [
|
|||
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
|
||||
Symfony\AI\AiBundle\AiBundle::class => ['all' => true],
|
||||
Symfony\AI\McpBundle\McpBundle::class => ['all' => true],
|
||||
League\Bundle\OAuth2ServerBundle\LeagueOAuth2ServerBundle::class => ['all' => true],
|
||||
];
|
||||
|
|
|
|||
43
config/packages/league_oauth2_server.yaml
Normal file
43
config/packages/league_oauth2_server.yaml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
## OAuth2 authorization server used for API/MCP app auto-provisioning (see docs/api/authentication.md).
|
||||
#
|
||||
# The bundle's own persistence layer (its Client/AccessToken/RefreshToken/AuthCode Doctrine entities) is
|
||||
# NOT used - "persistence: in_memory" here just satisfies the bundle's config schema (it registers a set
|
||||
# of trivial in-memory managers that some of the bundle's console commands/services still need to exist,
|
||||
# even though we never use them). The actual League\OAuth2\Server\Repositories\* interfaces are overridden
|
||||
# in config/services.yaml to point at our own Doctrine-backed repositories (App\Security\OAuth\Repository),
|
||||
# which make an OAuth2 access token just be a regular App\Entity\UserSystem\ApiToken row - see
|
||||
# App\Security\OAuth\Repository\AccessTokenRepository for why.
|
||||
league_oauth2_server:
|
||||
authorization_server:
|
||||
private_key: '%kernel.project_dir%/var/oauth2/private.key'
|
||||
private_key_passphrase: null
|
||||
encryption_key: '%env(OAUTH2_ENCRYPTION_KEY)%'
|
||||
encryption_key_type: 'defuse'
|
||||
access_token_ttl: 'PT1H'
|
||||
refresh_token_ttl: 'P30D'
|
||||
auth_code_ttl: 'PT10M'
|
||||
# Only Authorization Code (+ PKCE) and Refresh Token are supported - no client secrets, no
|
||||
# password grant, no implicit grant, no device code.
|
||||
enable_client_credentials_grant: false
|
||||
enable_password_grant: false
|
||||
enable_implicit_grant: false
|
||||
enable_device_code_grant: false
|
||||
enable_auth_code_grant: true
|
||||
enable_refresh_token_grant: true
|
||||
require_code_challenge_for_public_clients: true
|
||||
revoke_refresh_tokens: true
|
||||
response_type_class: App\Security\OAuth\OpaqueBearerTokenResponse
|
||||
resource_server:
|
||||
# Unused: we protect /api and /mcp with our own App\Security\ApiTokenAuthenticator, not the
|
||||
# bundle's resource-server/security integration. Still required by the bundle's config schema.
|
||||
public_key: '%kernel.project_dir%/var/oauth2/public.key'
|
||||
scopes:
|
||||
# Scopes are just the existing App\Entity\UserSystem\ApiTokenLevel enum - see App\Security\OAuth\OAuthScope.
|
||||
available: ['read_only', 'edit', 'admin', 'full']
|
||||
default: ['read_only']
|
||||
persistence:
|
||||
in_memory: ~
|
||||
client:
|
||||
# Irrelevant to us (we bypass the bundle's own client model entirely - see the top comment),
|
||||
# set to false just to silence the bundle's deprecation notice for the true default.
|
||||
allow_plaintext_secrets: false
|
||||
|
|
@ -1136,6 +1136,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* failure_forward?: bool|Param, // Default: false
|
||||
* failure_path_parameter?: scalar|Param|null, // Default: "_failure_path"
|
||||
* },
|
||||
* oauth2?: array<mixed>,
|
||||
* login_link?: array{
|
||||
* check_route?: scalar|Param|null, // Route that will validate the login link - e.g. "app_login_link_verify".
|
||||
* check_post_only?: scalar|Param|null, // If true, only HTTP POST requests to "check_route" will be handled by the authenticator. // Default: false
|
||||
|
|
@ -3230,6 +3231,60 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* },
|
||||
* },
|
||||
* }
|
||||
* @psalm-type LeagueOauth2ServerConfig = array{
|
||||
* authorization_server?: array{
|
||||
* private_key?: scalar|Param|null, // Full path to the private key file. How to generate a private key: https://oauth2.thephpleague.com/installation/#generating-public-and-private-keys
|
||||
* private_key_passphrase?: scalar|Param|null, // Passphrase of the private key, if any // Default: null
|
||||
* encryption_key?: scalar|Param|null, // The plain string or the ascii safe string used to create a Defuse\Crypto\Key to be used as an encryption key. How to generate an encryption key: https://oauth2.thephpleague.com/installation/#string-password
|
||||
* encryption_key_type?: scalar|Param|null, // The type of value of 'encryption_key' Should be either 'plain' or 'defuse' // Default: "plain"
|
||||
* access_token_ttl?: scalar|Param|null, // How long the issued access token should be valid for. The value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters // Default: "PT1H"
|
||||
* refresh_token_ttl?: scalar|Param|null, // How long the issued refresh token should be valid for. The value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters // Default: "P1M"
|
||||
* auth_code_ttl?: scalar|Param|null, // How long the issued auth code should be valid for. The value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters // Default: "PT10M"
|
||||
* device_code_ttl?: scalar|Param|null, // How long the issued device code should be valid for. The value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters // Default: "PT10M"
|
||||
* enable_client_credentials_grant?: bool|Param, // Whether to enable the client credentials grant // Default: true
|
||||
* enable_password_grant?: bool|Param, // Whether to enable the password grant
|
||||
* enable_refresh_token_grant?: bool|Param, // Whether to enable the refresh token grant // Default: true
|
||||
* enable_auth_code_grant?: bool|Param, // Whether to enable the authorization code grant // Default: true
|
||||
* require_code_challenge_for_public_clients?: bool|Param, // Whether to require code challenge for public clients for the auth code grant // Default: true
|
||||
* enable_implicit_grant?: bool|Param, // Whether to enable the implicit grant
|
||||
* persist_access_token?: bool|Param, // Whether to enable access token saving to persistence layer // Default: true
|
||||
* response_type_class?: scalar|Param|null, // Define a custom ResponseType // Default: null
|
||||
* revoke_refresh_tokens?: bool|Param, // Whether to revoke refresh tokens after they were used for all grant types // Default: true
|
||||
* enable_device_code_grant?: bool|Param, // Whether to enable the device code grant // Default: false
|
||||
* device_code_verification_uri?: scalar|Param|null, // The full URI the user will need to visit to enter the user code // Default: ""
|
||||
* enable_device_code_verification_uri_complete_generation?: bool|Param, // Whether to enable the generation of verification_uri_complete // Default: true
|
||||
* device_code_polling_interval?: scalar|Param|null, // How soon (in seconds) can the device code be used to poll for the access token without being throttled // Default: 5
|
||||
* enable_device_code_polling_interval_visibility?: bool|Param, // Whether to enable the visibility of polling interval // Default: true
|
||||
* },
|
||||
* resource_server?: array{
|
||||
* public_key?: scalar|Param|null, // Full path to the public key file How to generate a public key: https://oauth2.thephpleague.com/installation/#generating-public-and-private-keys
|
||||
* jwt_leeway?: scalar|Param|null, // The leeway in seconds to allow for clock skew in JWT verification. Default PT0S (no leeway). // Default: null
|
||||
* },
|
||||
* scopes?: array{
|
||||
* available?: list<scalar|Param|null>,
|
||||
* default?: list<scalar|Param|null>,
|
||||
* },
|
||||
* persistence?: array{ // Configures different persistence methods that can be used by the bundle for saving client and token data. Only one persistence method can be configured at a time.
|
||||
* doctrine?: array{
|
||||
* entity_manager?: scalar|Param|null, // Name of the entity manager that you wish to use for managing clients and tokens. // Default: "default"
|
||||
* table_prefix?: scalar|Param|null, // Table name prefix. // Default: "oauth2_"
|
||||
* },
|
||||
* in_memory?: scalar|Param|null,
|
||||
* custom?: array{
|
||||
* access_token_manager?: scalar|Param|null, // Service id of the custom access token manager
|
||||
* authorization_code_manager?: scalar|Param|null, // Service id of the custom authorization code manager
|
||||
* client_manager?: scalar|Param|null, // Service id of the custom client manager
|
||||
* refresh_token_manager?: scalar|Param|null, // Service id of the custom refresh token manager
|
||||
* device_code_manager?: scalar|Param|null, // Service id of the custom device code manager
|
||||
* credentials_revoker?: scalar|Param|null, // Service id of the custom credentials revoker
|
||||
* },
|
||||
* },
|
||||
* client?: array{
|
||||
* classname?: scalar|Param|null, // Set a custom client class. Must be a League\Bundle\OAuth2ServerBundle\Model\AbstractClient // Default: "League\\Bundle\\OAuth2ServerBundle\\Model\\Client"
|
||||
* allow_plaintext_secrets?: bool|Param, // Whether to allow plaintext client secrets. // Default: true
|
||||
* },
|
||||
* role_prefix?: scalar|Param|null, // Set a custom prefix that replaces the default 'ROLE_OAUTH2_' role prefix // Default: "ROLE_OAUTH2_"
|
||||
* }
|
||||
* @psalm-type ConfigType = array{
|
||||
* imports?: ImportsConfig,
|
||||
* parameters?: ParametersConfig,
|
||||
|
|
@ -3261,6 +3316,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* api_platform?: ApiPlatformConfig,
|
||||
* ai?: AiConfig,
|
||||
* mcp?: McpConfig,
|
||||
* league_oauth2_server?: LeagueOauth2ServerConfig,
|
||||
* "when@dev"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
* parameters?: ParametersConfig,
|
||||
|
|
@ -3296,6 +3352,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* api_platform?: ApiPlatformConfig,
|
||||
* ai?: AiConfig,
|
||||
* mcp?: McpConfig,
|
||||
* league_oauth2_server?: LeagueOauth2ServerConfig,
|
||||
* },
|
||||
* "when@docker"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
|
|
@ -3328,6 +3385,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* api_platform?: ApiPlatformConfig,
|
||||
* ai?: AiConfig,
|
||||
* mcp?: McpConfig,
|
||||
* league_oauth2_server?: LeagueOauth2ServerConfig,
|
||||
* },
|
||||
* "when@prod"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
|
|
@ -3360,6 +3418,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* api_platform?: ApiPlatformConfig,
|
||||
* ai?: AiConfig,
|
||||
* mcp?: McpConfig,
|
||||
* league_oauth2_server?: LeagueOauth2ServerConfig,
|
||||
* },
|
||||
* "when@test"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
|
|
@ -3395,6 +3454,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* api_platform?: ApiPlatformConfig,
|
||||
* ai?: AiConfig,
|
||||
* mcp?: McpConfig,
|
||||
* league_oauth2_server?: LeagueOauth2ServerConfig,
|
||||
* },
|
||||
* ...<string, ExtensionType|array{ // extra keys must follow the when@%env% pattern or match an extension alias
|
||||
* imports?: ImportsConfig,
|
||||
|
|
|
|||
3
config/routes/league_oauth2_server.yaml
Normal file
3
config/routes/league_oauth2_server.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
oauth2_server:
|
||||
resource: '@LeagueOAuth2ServerBundle/config/routes.php'
|
||||
type: php
|
||||
|
|
@ -140,6 +140,22 @@ services:
|
|||
$update_group_on_login: '%env(bool:SAML_UPDATE_GROUP_ON_LOGIN)%'
|
||||
|
||||
|
||||
####################################################################################################################
|
||||
# OAuth2 authorization server (auto-provisioning of API/MCP tokens, see docs/api/authentication.md)
|
||||
#
|
||||
# league/oauth2-server-bundle provides the /authorize and /token routes/controllers and builds the
|
||||
# League\OAuth2\Server\AuthorizationServer service from config/packages/league_oauth2_server.yaml, but
|
||||
# its own persistence layer is not used (see that file's top comment) - these overrides point the
|
||||
# core league/oauth2-server repository interfaces at our own Doctrine-backed implementations instead
|
||||
# of the bundle's, so an OAuth2 access token stays a plain App\Entity\UserSystem\ApiToken row.
|
||||
####################################################################################################################
|
||||
|
||||
League\OAuth2\Server\Repositories\ClientRepositoryInterface: '@App\Security\OAuth\Repository\ClientRepository'
|
||||
League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface: '@App\Security\OAuth\Repository\AccessTokenRepository'
|
||||
League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface: '@App\Security\OAuth\Repository\RefreshTokenRepository'
|
||||
League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface: '@App\Security\OAuth\Repository\AuthCodeRepository'
|
||||
League\OAuth2\Server\Repositories\ScopeRepositoryInterface: '@App\Security\OAuth\Repository\ScopeRepository'
|
||||
|
||||
security.access_token_extractor.header.token:
|
||||
class: Symfony\Component\Security\Http\AccessToken\HeaderAccessTokenExtractor
|
||||
arguments:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue