Enabling OAuth2 in Event Engine
In a recent project, we make use of the Event Engine which is an Event Sourcing framework for PHP helping you to rapidly develop event sourced applications. Since parts of the exposed API by the Event Engine should be access proteced, we decided to use OAuth2 for access delegation. That way each route exposed by the Event engine application can be marked as "protected" if needed.
Since the Event Engine makes use of the OpenAPI specification to describe the API, adding OAuth2 support can be added to the API definition itself. Adding OAuth 2 authentication was easier than expected, though you have to keep a few things in mind.
This is the main Swagger configuration that is generated in the MessageSchemaMiddleware of the Event Engine - stripped down to the relevant parts:
$paths = ; $componentSchemas = ; $schema = [ 'openapi' => '3.0.0', 'servers' => [ [ 'description' => 'My App', 'url' => (string) $serverUrl ] ], 'info' => [ 'description' => 'An endpoint for sending messages to my app', 'version' => 'v1.0.0', 'title' => 'My app' ], 'paths' => $paths, 'components' => ['schemas' => $componentSchemas], ];
To enable OAuth2 support add a "securitySchemes" section to the components part so that it looks like this:
'components' => [ 'schemas' => $componentSchemas, 'securitySchemes' => $securitySchemes ]
The securitySchemes configuration for our use case is defined like this:
$securitySchemes['oauth'] = [ 'type' => 'oauth2', 'description' => 'Uses OAuth 2 clientCredentials grant flow', 'flows' => [ 'clientCredentials' => [ 'tokenUrl' => '/api/access_token', 'scopes' => [ 'app' => 'Access to public APIs', 'admin' => 'Access to admin APIs' ] ] ] ];
The array key "oauth" in $securitySchemes will be needed later to refer to this security configuration. The "type" defines the configuration as being an Oauth2 flow and the "flows" sections configures the client credentials authentication which is a standard in OAuth2. Since Swagger consumers need to know the url to generate the access token as well as the scopes the OAuth2 authentication provides, we add both to the configuration section. In our case we deal with 2 scopes, one is called app and the other is called admin.
To configure the security schema for a route, you need to add a security section which contains an array of arrays (important!) and maps the $securitySchemes identifier to the OAuth2 scope like this:
[ "/my-route", [ 'post' => [ // [...] 'security' => [['oauth' => 'app']], ] ] ];
This means the /my-route can only be accessed by a user who has the OAuth2 scope called "app" set. If you are using the Swagger UI for example, the UI will render a login form where a user can request the different scopes during the login, this makes it easy to test the setup.