thephpleague / oauth2-server

A spec compliant, secure by default PHP OAuth 2.0 Server
https://oauth2.thephpleague.com
MIT License
6.52k stars 1.12k forks source link

TypeError in mallformed tokens #1209

Closed marc-mabe closed 3 years ago

marc-mabe commented 3 years ago

I'm using https://github.com/mezzio/mezzio-authentication-oauth2 and noticed thousands of 500 errors on our server. (Someone tried to access something he should not but I don't expect this bug a security issue.)

The problem happens if someone passes a token not as string.

E.g:

        $data = [
            'grant_type'    => 'refresh_token',
            'refresh_token' => ['not', 'a', 'string'],
            'client_id'     => $ssoClient['client_id'],
            'client_secret' => $ssoClient['client_secret'],
        ];
        $I->sendPOST('/oauth2/token', $data);
        $I->seeResponseCodeIs(401);
TypeError raised in file /app/vendor/defuse/php-encryption/src/Crypto.php line 136:
Message: String expected for argument 1. Array given instead.
Stack Trace:
#0 /app/vendor/league/oauth2-server/src/CryptTrait.php(69): Defuse\Crypto\Crypto::decryptWithPassword(Array, '/app/config/aut...')
#1 /app/vendor/league/oauth2-server/src/Grant/RefreshTokenGrant.php(107): League\OAuth2\Server\Grant\AbstractGrant->decrypt(Array)
#2 /app/vendor/league/oauth2-server/src/Grant/RefreshTokenGrant.php(47): League\OAuth2\Server\Grant\RefreshTokenGrant->validateOldRefreshToken(Object(Laminas\Diactoros\ServerRequest), 'accounts.fronte...')
#3 /app/vendor/league/oauth2-server/src/AuthorizationServer.php(198): League\OAuth2\Server\Grant\RefreshTokenGrant->respondToAccessTokenRequest(Object(Laminas\Diactoros\ServerRequest), Object(League\OAuth2\Server\ResponseTypes\BearerTokenResponse), Object(DateInterval))
#4 /app/vendor/mezzio/mezzio-authentication-oauth2/src/TokenEndpointHandler.php(71): League\OAuth2\Server\AuthorizationServer->respondToAccessTokenRequest(Object(Laminas\Diactoros\ServerRequest), Object(Laminas\Diactoros\Response))

The bug seems to be fixed with but other grant types are very likely effected, too

        if (!\is_string($encryptedRefreshToken)) {
            throw OAuthServerException::invalidRefreshToken('Refresh token mallformed');
        }
eugene-borovov commented 3 years ago

You can add a middleware to filter the request.

class FixRefreshToken implements MiddlewareInterface
{
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface    
    {
        $params = $request->getParsedBody();
        if (isset($params['refresh_token']) && !is_string($params['refresh_token'])) {
           $params['refresh_token'] = (string)$params['refresh_token'];            
           $request = $request->withParsedBody(params);
        }

        return $handler->handle($request);
    }
}