thephpleague / oauth2-client

Easy integration with OAuth 2.0 service providers.
http://oauth2-client.thephpleague.com
MIT License
3.64k stars 751 forks source link

How to catch if oauth2 service is in maintenance mode #934

Open prodigy7 opened 2 years ago

prodigy7 commented 2 years ago

I am currently trying to implement the client in such a way that I am notified when the OAuth2 service is in maintenance mode, i.e. when it returns an HTTP status code 503. Unfortunately, maybe I'm blind, I don't see any way to get to this status code. I currently get the following message:

InvalidArgumentException {#410 ▼
  #message: "Required option not passed: "access_token""
  #code: 0
  #file: "/var/www/vhosts/htdocs/vendor/league/oauth2-client/src/Token/AccessToken.php"
  #line: 62
  trace: {▼
    /var/www/vhosts/htdocs/vendor/league/oauth2-client/src/Token/AccessToken.php:62 {▶}
    /var/www/vhosts/htdocs/vendor/league/oauth2-client/src/Provider/AbstractProvider.php:746 {▶}
    /var/www/vhosts/htdocs/vendor/league/oauth2-client/src/Provider/AbstractProvider.php:544 {▶}

Unfortunately, I cannot use this to determine whether the service is in maintenance mode and I can display a corresponding clean message on my page. Is it possible to implement a way to get this information?

prodigy7 commented 2 years ago

So far I identified the file src/Provider/AbstractProvider.php:

    public function getParsedResponse(RequestInterface $request)
    {
        try {
            $response = $this->getResponse($request);
        } catch (BadResponseException $e) {
            $response = $e->getResponse();
        }

I think it's not such a good idea to just catch the error here and pass it on as some kind of regular feedback. In my opinion, an exception should be thrown cleanly as such, so that I can then also deal specifically with the error, as in this case. When I put the OAuth2 server into maintenance mode, it returns a code 503. Currently, your implementation only returns the message that the access token is not set, if I want to retrieve it. In reality, however, the error is that the server does not respond with the status with which it should respond. The actual error is cascaded through another message and made unrecognisable.

My proposed change would be as follows, although I am aware that tests may fail or that it may also represent a breaking change:

    public function getParsedResponse(RequestInterface $request)
    {
        try {
            $response = $this->getResponse($request);
        } catch (BadResponseException $e) {
            throw new \Exception($e->getMessage(), $e->getCode());
        }

Maybe it's a solution, implement public function getAccessToken($grant, array $options = []) with an additional argument , $throwPlanException = false or something like that and add also that argument to getParsedResponse and build there an condition. If $throwPlanException = false, handle everything on the old way. If $throwPlanException = true, throw the exception?

Like that:

    public function getParsedResponse(RequestInterface $request, $throwPlanException = false)
    {
        try {
            $response = $this->getResponse($request);
        } catch (BadResponseException $e) {
            if($throwPlanException) {
                $response = $e->getResponse();
            } else {
                throw new \Exception($e->getMessage(), $e->getCode());
            }
        }

It adds a new functionality without being a breaking change.