oauth2-keycloak
oauth2-keycloak copied to clipboard
Failed to parse JSON response
Hello.
When executing: $provider->getResourceOwner($token);
I got this error: Failed to parse JSON response: Syntax error /vendor/league/oauth2-client/src/Provider/AbstractProvider.php on line 645
Checked the token on jwt.io - it's ok
How to fix it?
firebase/php-jwt (v6.4.0) guzzlehttp/guzzle (7.5.0) guzzlehttp/promises (1.5.2) guzzlehttp/psr7 (2.4.4) league/oauth2-client (2.6.1) paragonie/random_compat (v9.99.100) psr/http-client (1.0.1) psr/http-factory (1.0.1) psr/http-message (1.0.1) ralouphie/getallheaders (3.0.3) stevenmaguire/oauth2-keycloak (4.0.0) symfony/deprecation-contracts (v2.5.2)
I am also facing the same problem Failed to parse JSON response: Syntax error
.
Repro steps
The example below is of the code I am running and getting error:
<?php
declare(strict_types=1);
namespace Application\Controller;
use Exception;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Stevenmaguire\OAuth2\Client\Provider\Keycloak;
class AuthCallbackController
{
/**
* @param Keycloak $provider
*/
public function __construct(private Keycloak $provider)
{
}
/**
* @param Request $request
* @param Response $response
* @return Response
*/
public function __invoke(Request $request, Response $response): Response
{
$params = $request->getQueryParams();
$token = $this->provider->getAccessToken('authorization_code', ['code' => $params['code']]);
$user_data = $this->provider->getResourceOwner($token);
return $response->withStatus(200)
->withHeader('Content-Type', 'application/json');
}
}
Screenshots
Environment settings
- Keycloak 21.0.2
- PHP 8.2
See the output of the composer show -i
command:
fig/http-message-util 1.1.5 Utility classes and constants for use with PSR-7 (psr/http-message)
firebase/php-jwt v6.4.0 A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.
guzzlehttp/guzzle 7.5.0 Guzzle is a PHP HTTP client library
guzzlehttp/promises 1.5.2 Guzzle promises library
guzzlehttp/psr7 2.4.4 PSR-7 message implementation that also provides common utility methods
laravel/serializable-closure v1.3.0 Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.
league/oauth2-client 2.6.1 OAuth 2.0 Client Library
nikic/fast-route v1.3.0 Fast request router for PHP
paragonie/random_compat v9.99.100 PHP 5.x polyfill for random_bytes() and random_int() from PHP 7
php-di/invoker 2.3.3 Generic and extensible callable invoker
php-di/php-di 7.0.2 The dependency injection container for humans
php-di/slim-bridge 3.3.0 PHP-DI integration in Slim
psr/container 2.0.2 Common Container Interface (PHP FIG PSR-11)
psr/http-client 1.0.2 Common interface for HTTP clients
psr/http-factory 1.0.2 Common interfaces for PSR-7 HTTP message factories
psr/http-message 1.1 Common interface for HTTP messages
psr/http-server-handler 1.0.2 Common interface for HTTP server-side request handler
psr/http-server-middleware 1.0.2 Common interface for HTTP server-side middleware
psr/log 3.0.0 Common interface for logging libraries
ralouphie/getallheaders 3.0.3 A polyfill for getallheaders.
slim/http 1.3 Slim PSR-7 Object Decorators
slim/psr7 1.6 Strict PSR-7 implementation
slim/slim 4.11.0 Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs
stevenmaguire/oauth2-keycloak 4.0.0 Keycloak OAuth 2.0 Client Provider for The PHP League OAuth2-Client
symfony/deprecation-contracts v3.2.1 A generic function and convention to trigger deprecation notices
symfony/polyfill-php80 v1.27.0 Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions
Yeah I'm facing the same issue too. I poked around a little and found that in fact, the 'openid' scope is needed for the userinfo. There is a switch "if ($this->validateGteVersion('20.0.0')) {"
in Line 210 of Keycloak.php but that does not seem to work anymore. If the condition is true, the 'openid' scope is added to the default scopes.
If I add the 'openid' scope in the default scopes above by hand Line 208 of Keycloak.php, everything works fine
Yeah I'm facing the same issue too. I poked around a little and found that in fact, the 'openid' scope is needed for the userinfo. There is a switch
"if ($this->validateGteVersion('20.0.0')) {"
in Line 210 of Keycloak.php but that does not seem to work anymore. If the condition is true, the 'openid' scope is added to the default scopes.If I add the 'openid' scope in the default scopes above by hand Line 208 of Keycloak.php, everything works fine
@redor303 i deeply appreciate your feedback, as it helped me solve my problem. According to the official library documentation on Github, the version parameter in the dependency constructor is optional. However, I believe that users who are using versions higher than 20 of Keycloak will need to specify this parameter.
Here's my Keycloak constructor looks:
new Keycloak([
'authServerUrl' => getenv('AUTH_SERVER_URL'),
'realm' => getenv('REALM'),
'clientId' => getenv('CLIENT_ID'),
'clientSecret' => getenv('CLIENT_SECRET'),
'redirectUri' => getenv('REDIRECT_URI'),
'version' => '21.0.2', # Add this parameter to troubleshoot the issue
]);
After configuring the parameter and making a new request, I was able to confirm that everything is working correctly. Now it's possible to retrieve user information without encountering the Forbidden 403 error
. That was causing the request to come empty and generate the error in parse JSON response.
Screenshot of example:
I hadn't noticed the version issue, and only understood the situation better after your explanation. I'm very grateful for your feedback and the clarity of your explanation.
Upon upgrade of our Keycloak server to 21, login with that library suddenly stopped working. This ought to be more robust; especially with a version
parameter marked as optional.
Thank you so much for pointing this out. I was facing the same issue and wasn't able to fix that >] With added scope openid it works
Next week I will look at and prepare fix
Thank you so much, i lost hours trying to solve the problem after the system team upgraded their Keycloak version...
openid
Yes, I managed to make things work using these parameters:
$provider->getAccessToken('password', [
'username' => 'username',
'password' => 'password',
'scope' => 'openid', // <=== required, in my case
'version' => '25.0.1'
]);
@matteo-piazza-exm your solution is working thanks