Configuration problem using zend-expressive-authentication-oauth2, HTTP 500

I’m very new in zend-expressive and used the skeleton app as entry point. Now I want to protect my API using zend-expressive-authentication-oauth2 and have some problems to get it working. The system is PHP 7.2 (Debian) and all packages installed via composer in the latest versions.
I followed the instructions to install and configure the module: I created the *.key files under data/oauth, used the SQL script to create the database tables and made the modifications in the app configs.
What happens is that I get an HTTP 500 error if I call the following URL in a browser:

example.com/api/ping

And the same if I post client credentials to the URL:

example.com/oauth2/token

So I guess there’s something wrong with the configuration. Unfortunately the error page displays no concrete error message so debugging is quite difficult. But I try to show my files so exact as possible.

config/config.php

$aggregator = new ConfigAggregator([
    \Zend\Expressive\Authentication\ConfigProvider::class,
    // ...
    MyProject\Api\ConfigProvider::class,
    new PhpFileProvider(realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php'),
], $cacheConfig['config_cache_path']);

config/autoload/dependencies.global.php

<?php

declare(strict_types=1);

use Zend\Expressive\Authentication;

return [
    'dependencies' => [
        'aliases' => [
            Authentication\AuthenticationInterface::class => Authentication\OAuth2\OAuth2Adapter::class,
        ],
        'invokables' => [
        ],
        'factories'  => [
        ],
    ],
];

config/autoload/oauth2.global.php

<?php

declare(strict_types=1);

use League\OAuth2\Server\Grant;

return [
    'authentication' => [
        'private_key' => dirname(__DIR__) . '/../data/oauth/private.key',
        'public_key' => dirname(__DIR__) . '/../data/oauth/public.key',
        'encryption_key' => require dirname(__DIR__) . '/../data/oauth/encryption.key',

        'access_token_expire' => 'P1D',
        'refresh_token_expire' => 'P1M',
        'auth_code_expire' => 'PT10M',

        'pdo' => [
            'dsn' => sprintf(
                'mysql:dbname=%s;host=%s',
                false !== getenv('MYSQL_DB_NAME') ? getenv('MYSQL_DB_NAME') : '',
                false !== getenv('MYSQL_DB_HOST') ? getenv('MYSQL_DB_HOST') : ''
            ),
            'username' => false !== getenv('MYSQL_DB_USER') ? getenv('MYSQL_DB_USER') : '',
            'password' => false !== getenv('MYSQL_DB_PASS') ? getenv('MYSQL_DB_PASS') : '',
        ],

        'grants' => [
            Grant\ClientCredentialsGrant::class => Grant\ClientCredentialsGrant::class,
            Grant\PasswordGrant::class => Grant\PasswordGrant::class,
            Grant\AuthCodeGrant::class => Grant\AuthCodeGrant::class,
            Grant\ImplicitGrant::class => Grant\ImplicitGrant::class,
            Grant\RefreshTokenGrant::class => Grant\RefreshTokenGrant::class,
        ],
    ],
];

config/autoload/pipeline.php

No modifications.

config/routes.php

<?php

declare(strict_types=1);

use MyProject\Api\Handler\HomePageHandler;
use MyProject\Api\Handler\PingHandler;
use Psr\Container\ContainerInterface;
use Zend\Expressive\Application;
use Zend\Expressive\Authentication\AuthenticationMiddleware;
use Zend\Expressive\Authentication\OAuth2\TokenEndpointHandler;
use Zend\Expressive\MiddlewareFactory;

return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void {
    $app->post('/oauth2/token', TokenEndpointHandler::class);

    $app->get('/', HomePageHandler::class, 'home');
    $app->get('/api/ping', [
        AuthenticationMiddleware::class,
        PingHandler::class,
    ], 'api.ping');
};

You’re going to need to find the error message. Sounds like your environment isn’t setup to display errors to screen. Hopefully you have a log somewhere depending on your env. The OAuth2 setup can be a bit tricky but that trickiness is exacerbated by lack of error message availability. Fix your error reporting/logging first.

Ok, the application crashes with an InvalidConfigException and the message: “AuthenticationInterface service is missing”. The exception is be thrown by the AuthenticationMiddlewareFactory class.

You have the base config for Expressive’s auth lib, \Zend\Expressive\Authentication\ConfigProvider::class in your config.php but you do not have the config for the OAuth2 adapter lib config there (unless you removed it for this post). You should be able to get past this error by adding the OAuth2 config to config.php. Something like:

$aggregator = new ConfigAggregator([
    \Zend\Expressive\Authentication\ConfigProvider::class,
    \Zend\Expressive\Authentication\OAuth2\ConfigProvider::class,
    // ...
    MyProject\Api\ConfigProvider::class,
    new PhpFileProvider(realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php'),
], $cacheConfig['config_cache_path']);

Of course you’ll need the zendframework/zend-expressive-authentication-oauth2 package installed first.