From be5e4b1589f74edc7414f1c8ed63b96ef9205204 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Fri, 17 Jan 2014 15:37:07 +0000 Subject: [PATCH] Intercept auth rejections requiring an OTP token --- src/Composer/Util/GitHub.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Composer/Util/GitHub.php b/src/Composer/Util/GitHub.php index 49e56f8c9..affae8c64 100644 --- a/src/Composer/Util/GitHub.php +++ b/src/Composer/Util/GitHub.php @@ -111,6 +111,34 @@ class GitHub ))); } catch (TransportException $e) { if (in_array($e->getCode(), array(403, 401))) { + // 401 when authentication was supplied, handle 2FA if required. + if ($this->io->hasAuthentication($originUrl)) { + $headerNames = array_map(function($header) { + return strstr($header, ':', true); + }, $e->getHeaders()); + + if ($key = array_search('X-GitHub-OTP', $headerNames)) { + $headers = $e->getHeaders(); + list($required, $method) = array_map('trim', explode(';', substr(strstr($headers[$key], ':'), 1))); + + if ('required' === $required) { + $this->io->write('Two-factor Authentication'); + + if ('app' === $method) { + $this->io->write('Open the two-factor authentication app on your device to view your authentication code and verify your identity.'); + } + + if ('sms' === $method) { + // @todo + } + + $otp = $this->io->ask('Authentication Code: '); + + continue; + } + } + } + $this->io->write('Invalid credentials.'); continue; }