From eec78a70949bcaeb3eeb3808369f21dda06038a3 Mon Sep 17 00:00:00 2001 From: "Eirik S. Morland" Date: Wed, 29 Jul 2020 09:03:41 +0200 Subject: [PATCH 1/7] Add support for SSO errors coming from the API --- lib/Github/Exception/SsoRequiredException.php | 25 +++++++++++++++++++ .../Plugin/GithubExceptionThrower.php | 11 ++++++++ 2 files changed, 36 insertions(+) create mode 100644 lib/Github/Exception/SsoRequiredException.php diff --git a/lib/Github/Exception/SsoRequiredException.php b/lib/Github/Exception/SsoRequiredException.php new file mode 100644 index 00000000000..b2e02608429 --- /dev/null +++ b/lib/Github/Exception/SsoRequiredException.php @@ -0,0 +1,25 @@ +url = $url; + + parent::__construct('Resource protected by organization SAML enforcement. You must grant your personal token access to this organization.', $code, $previous); + } + + + public function getUrl() + { + return $this->url; + } + +} diff --git a/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php b/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php index 60382074a40..b16ec620308 100644 --- a/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php +++ b/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php @@ -5,6 +5,7 @@ use Github\Exception\ApiLimitExceedException; use Github\Exception\ErrorException; use Github\Exception\RuntimeException; +use Github\Exception\SsoRequiredException; use Github\Exception\TwoFactorAuthenticationRequiredException; use Github\Exception\ValidationFailedException; use Github\HttpClient\Message\ResponseMediator; @@ -103,6 +104,16 @@ public function doHandleRequest(RequestInterface $request, callable $next, calla throw new RuntimeException(implode(', ', $errors), 502); } + if ((403 === $response->getStatusCode()) && $response->hasHeader('X-GitHub-SSO') && 0 === strpos((string) ResponseMediator::getHeader($response, 'X-GitHub-SSO'), 'required;')) { + // The header will look something like this: + // required; url=https://github.com/orgs/octodocs-test/sso?authorization_request=AZSCKtL4U8yX1H3sCQIVnVgmjmon5fWxks5YrqhJgah0b2tlbl9pZM4EuMz4 + // So we strip out the first 14 characters, leaving only the URL. + // @see https://developer.github.com/v3/auth/#authenticating-for-saml-sso + $url = substr((string) ResponseMediator::getHeader($response, 'X-GitHub-SSO'), 14); + + throw new SsoRequiredException($url); + } + throw new RuntimeException(isset($content['message']) ? $content['message'] : $content, $response->getStatusCode()); }); } From 282fd585d53a3129e2cc382b5c96253c037de4de Mon Sep 17 00:00:00 2001 From: "Eirik S. Morland" Date: Wed, 29 Jul 2020 09:05:53 +0200 Subject: [PATCH 2/7] Code style --- lib/Github/Exception/SsoRequiredException.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/Github/Exception/SsoRequiredException.php b/lib/Github/Exception/SsoRequiredException.php index b2e02608429..443b7b75580 100644 --- a/lib/Github/Exception/SsoRequiredException.php +++ b/lib/Github/Exception/SsoRequiredException.php @@ -16,10 +16,8 @@ public function __construct($url, $code = 0, $previous = null) parent::__construct('Resource protected by organization SAML enforcement. You must grant your personal token access to this organization.', $code, $previous); } - public function getUrl() { return $this->url; } - } From 9a9bec73a0e374b036204d77e342521c532d0b10 Mon Sep 17 00:00:00 2001 From: "Eirik S. Morland" Date: Wed, 29 Jul 2020 09:15:43 +0200 Subject: [PATCH 3/7] phpstan fixes --- lib/Github/Exception/SsoRequiredException.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/Github/Exception/SsoRequiredException.php b/lib/Github/Exception/SsoRequiredException.php index 443b7b75580..c409361f03b 100644 --- a/lib/Github/Exception/SsoRequiredException.php +++ b/lib/Github/Exception/SsoRequiredException.php @@ -7,8 +7,14 @@ */ class SsoRequiredException extends RuntimeException { + /** @var string */ private $url; + /** + * @param string $url + * @param int $code + * @param \Throwable|null $previous + */ public function __construct($url, $code = 0, $previous = null) { $this->url = $url; @@ -16,6 +22,9 @@ public function __construct($url, $code = 0, $previous = null) parent::__construct('Resource protected by organization SAML enforcement. You must grant your personal token access to this organization.', $code, $previous); } + /** + * @return string + */ public function getUrl() { return $this->url; From 51b49cba2d42494dbb82bb874d3f3ec2efe3f3ff Mon Sep 17 00:00:00 2001 From: "Eirik S. Morland" Date: Sat, 15 Aug 2020 14:45:56 +0200 Subject: [PATCH 4/7] Code style --- lib/Github/Exception/SsoRequiredException.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Github/Exception/SsoRequiredException.php b/lib/Github/Exception/SsoRequiredException.php index c409361f03b..6a47eea7738 100644 --- a/lib/Github/Exception/SsoRequiredException.php +++ b/lib/Github/Exception/SsoRequiredException.php @@ -11,8 +11,8 @@ class SsoRequiredException extends RuntimeException private $url; /** - * @param string $url - * @param int $code + * @param string $url + * @param int $code * @param \Throwable|null $previous */ public function __construct($url, $code = 0, $previous = null) From e566606dc2ceb81f5f21c5accf6dcce9f108a0ce Mon Sep 17 00:00:00 2001 From: "Eirik S. Morland" Date: Sat, 15 Aug 2020 14:54:15 +0200 Subject: [PATCH 5/7] Add a test for sso required exception --- .../HttpClient/Plugin/GithubExceptionThrowerTest.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php index 32be44ce1d5..c279f1b9271 100644 --- a/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php +++ b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php @@ -3,6 +3,7 @@ namespace Github\Tests\HttpClient\Plugin; use Github\Exception\ExceptionInterface; +use Github\Exception\SsoRequiredException; use Github\HttpClient\Plugin\GithubExceptionThrower; use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Psr7\Response; @@ -136,6 +137,16 @@ public static function responseProvider() ), 'exception' => new \Github\Exception\RuntimeException('Something went wrong with executing your query', 502), ], + 'Sso required Response' => [ + 'response' => new Response( + 403, + [ + 'Content-Type' => 'application/json', + 'X-GitHub-SSO' => 'required; url=https://github.com/orgs/octodocs-test/sso?authorization_request=AZSCKtL4U8yX1H3sCQIVnVgmjmon5fWxks5YrqhJgah0b2tlbl9pZM4EuMz4', + ] + ), + 'exception' => new \Github\Exception\SsoRequiredException('https://github.com/orgs/octodocs-test/sso?authorization_request=AZSCKtL4U8yX1H3sCQIVnVgmjmon5fWxks5YrqhJgah0b2tlbl9pZM4EuMz4') + ], 'Default handling' => [ 'response' => new Response( 555, From 4588ad53175b3c79b4ff050a5a3503ceb892c11a Mon Sep 17 00:00:00 2001 From: "Eirik S. Morland" Date: Sat, 15 Aug 2020 14:54:55 +0200 Subject: [PATCH 6/7] Code style --- .../Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php index c279f1b9271..620fc1d2cb0 100644 --- a/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php +++ b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php @@ -3,7 +3,6 @@ namespace Github\Tests\HttpClient\Plugin; use Github\Exception\ExceptionInterface; -use Github\Exception\SsoRequiredException; use Github\HttpClient\Plugin\GithubExceptionThrower; use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Psr7\Response; From 54cf8f179b192ba3e6c5739cf3525eedefb32bee Mon Sep 17 00:00:00 2001 From: "Eirik S. Morland" Date: Sat, 15 Aug 2020 14:55:36 +0200 Subject: [PATCH 7/7] Code style --- .../Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php index 620fc1d2cb0..7011e1fe6bb 100644 --- a/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php +++ b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php @@ -144,7 +144,7 @@ public static function responseProvider() 'X-GitHub-SSO' => 'required; url=https://github.com/orgs/octodocs-test/sso?authorization_request=AZSCKtL4U8yX1H3sCQIVnVgmjmon5fWxks5YrqhJgah0b2tlbl9pZM4EuMz4', ] ), - 'exception' => new \Github\Exception\SsoRequiredException('https://github.com/orgs/octodocs-test/sso?authorization_request=AZSCKtL4U8yX1H3sCQIVnVgmjmon5fWxks5YrqhJgah0b2tlbl9pZM4EuMz4') + 'exception' => new \Github\Exception\SsoRequiredException('https://github.com/orgs/octodocs-test/sso?authorization_request=AZSCKtL4U8yX1H3sCQIVnVgmjmon5fWxks5YrqhJgah0b2tlbl9pZM4EuMz4'), ], 'Default handling' => [ 'response' => new Response(