Skip to content

Commit 6688f21

Browse files
committed
feat(AuthHelper): add addAuthenticationOptions, deprecate addAuthenticationHeader
1 parent e8adca0 commit 6688f21

File tree

5 files changed

+119
-39
lines changed

5 files changed

+119
-39
lines changed

phpstan/baseline.neon

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4446,6 +4446,14 @@ parameters:
44464446
count: 1
44474447
path: ../tests/Composer/Test/TestCase.php
44484448

4449+
-
4450+
message: """
4451+
#^Call to deprecated method addAuthenticationHeader\\(\\) of class Composer\\\\Util\\\\AuthHelper\\:
4452+
use addAuthenticationOptions instead$#
4453+
"""
4454+
count: 3
4455+
path: ../tests/Composer/Test/Util/AuthHelperTest.php
4456+
44494457
-
44504458
message: "#^Cannot access an offset on array\\<int, array\\<string, array\\<int, string\\>\\|int\\|string\\>\\>\\|false\\.$#"
44514459
count: 2

src/Composer/Util/AuthHelper.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,35 @@ public function promptAuthIfNeeded(string $url, string $origin, int $statusCode,
227227
}
228228

229229
/**
230+
* @deprecated use addAuthenticationOptions instead
231+
*
230232
* @param string[] $headers
231233
*
232234
* @return string[] updated headers array
233235
*/
234236
public function addAuthenticationHeader(array $headers, string $origin, string $url): array
235237
{
238+
trigger_error('AuthHelper::addAuthenticationHeader is deprecated since Composer 2.9 use addAuthenticationOptions instead.', E_USER_DEPRECATED);
239+
240+
$options = ['http' => ['header' => &$headers]];
241+
$options = $this->addAuthenticationOptions($options, $origin, $url);
242+
return $options['http']['header'];
243+
}
244+
245+
/**
246+
* @param array<string, mixed> $options
247+
*
248+
* @return array<string, mixed> updated options
249+
*/
250+
public function addAuthenticationOptions(array $options, string $origin, string $url): array
251+
{
252+
if (!isset($options['http'])) {
253+
$options['http'] = [];
254+
}
255+
if (!isset($options['http']['header'])) {
256+
$options['http']['header'] = [];
257+
}
258+
$headers = &$options['http']['header'];
236259
if ($this->io->hasAuthentication($origin)) {
237260
$authenticationDisplayMessage = null;
238261
$auth = $this->io->getAuthentication($origin);
@@ -287,10 +310,10 @@ public function addAuthenticationHeader(array $headers, string $origin, string $
287310
$this->displayedOriginAuthentications[$origin] = $authenticationDisplayMessage;
288311
}
289312
} elseif (in_array($origin, ['api.bitbucket.org', 'api.github.com'], true)) {
290-
return $this->addAuthenticationHeader($headers, str_replace('api.', '', $origin), $url);
313+
return $this->addAuthenticationOptions($options, str_replace('api.', '', $origin), $url);
291314
}
292315

293-
return $headers;
316+
return $options;
294317
}
295318

296319
/**

src/Composer/Util/Http/CurlDownloader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ private function initDownload(callable $resolve, callable $reject, string $origi
253253
curl_setopt($curlHandle, CURLOPT_ENCODING, "gzip");
254254
}
255255

256-
$options['http']['header'] = $this->authHelper->addAuthenticationHeader($options['http']['header'], $origin, $url);
256+
$options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
257257
$options = StreamContextFactory::initOptions($url, $options, true);
258258

259259
foreach (self::$options as $type => $curlOptions) {

src/Composer/Util/RemoteFilesystem.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,13 +632,13 @@ protected function getOptionsForUrl(string $originUrl, array $additionalOptions)
632632
$headers[] = 'Connection: close';
633633
}
634634

635-
$headers = $this->authHelper->addAuthenticationHeader($headers, $originUrl, $this->fileUrl);
636-
637-
$options['http']['follow_location'] = 0;
638-
639635
if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
640636
$options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
641637
}
638+
$options = $this->authHelper->addAuthenticationOptions($options, $originUrl, $this->fileUrl);
639+
640+
$options['http']['follow_location'] = 0;
641+
642642
foreach ($headers as $header) {
643643
$options['http']['header'][] = $header;
644644
}

tests/Composer/Test/Util/AuthHelperTest.php

Lines changed: 81 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public function testAddAuthenticationHeaderWithoutAuthCredentials(): void
4949
'Accept-Encoding: gzip',
5050
'Connection: close',
5151
];
52+
$options = ['http' => ['header' => $headers]];
5253
$origin = 'http://example.org';
5354
$url = 'file://' . __FILE__;
5455

@@ -57,10 +58,9 @@ public function testAddAuthenticationHeaderWithoutAuthCredentials(): void
5758
->with($origin)
5859
->willReturn(false);
5960

60-
self::assertSame(
61-
$headers,
62-
$this->authHelper->addAuthenticationHeader($headers, $origin, $url)
63-
);
61+
$options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
62+
63+
self::assertSame($headers, $options['http']['header']);
6464
}
6565

6666
public function testAddAuthenticationHeaderWithBearerPassword(): void
@@ -69,6 +69,7 @@ public function testAddAuthenticationHeaderWithBearerPassword(): void
6969
'Accept-Encoding: gzip',
7070
'Connection: close',
7171
];
72+
$options = ['http' => ['header' => $headers]];
7273
$origin = 'http://example.org';
7374
$url = 'file://' . __FILE__;
7475
$auth = [
@@ -80,10 +81,9 @@ public function testAddAuthenticationHeaderWithBearerPassword(): void
8081

8182
$expectedHeaders = array_merge($headers, ['Authorization: Bearer ' . $auth['username']]);
8283

83-
self::assertSame(
84-
$expectedHeaders,
85-
$this->authHelper->addAuthenticationHeader($headers, $origin, $url)
86-
);
84+
$options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
85+
86+
self::assertSame($expectedHeaders, $options['http']['header']);
8787
}
8888

8989
public function testAddAuthenticationHeaderWithGithubToken(): void
@@ -92,6 +92,7 @@ public function testAddAuthenticationHeaderWithGithubToken(): void
9292
'Accept-Encoding: gzip',
9393
'Connection: close',
9494
];
95+
$options = ['http' => ['header' => $headers]];
9596
$origin = 'github.com';
9697
$url = 'https://api.github.com/';
9798
$auth = [
@@ -106,11 +107,9 @@ public function testAddAuthenticationHeaderWithGithubToken(): void
106107
->with('Using GitHub token authentication', true, IOInterface::DEBUG);
107108

108109
$expectedHeaders = array_merge($headers, ['Authorization: token ' . $auth['username']]);
110+
$options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
109111

110-
self::assertSame(
111-
$expectedHeaders,
112-
$this->authHelper->addAuthenticationHeader($headers, $origin, $url)
113-
);
112+
self::assertSame($expectedHeaders, $options['http']['header']);
114113
}
115114

116115
public function testAddAuthenticationHeaderWithGitlabOathToken(): void
@@ -119,6 +118,7 @@ public function testAddAuthenticationHeaderWithGitlabOathToken(): void
119118
'Accept-Encoding: gzip',
120119
'Connection: close',
121120
];
121+
$options = ['http' => ['header' => $headers]];
122122
$origin = 'gitlab.com';
123123
$url = 'https://api.gitlab.com/';
124124
$auth = [
@@ -138,11 +138,9 @@ public function testAddAuthenticationHeaderWithGitlabOathToken(): void
138138
->with('Using GitLab OAuth token authentication', true, IOInterface::DEBUG);
139139

140140
$expectedHeaders = array_merge($headers, ['Authorization: Bearer ' . $auth['username']]);
141+
$options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
141142

142-
self::assertSame(
143-
$expectedHeaders,
144-
$this->authHelper->addAuthenticationHeader($headers, $origin, $url)
145-
);
143+
self::assertSame($expectedHeaders, $options['http']['header']);
146144
}
147145

148146
public static function gitlabPrivateTokenProvider(): array
@@ -162,6 +160,7 @@ public function testAddAuthenticationHeaderWithGitlabPrivateToken(string $passwo
162160
'Accept-Encoding: gzip',
163161
'Connection: close',
164162
];
163+
$options = ['http' => ['header' => $headers]];
165164
$origin = 'gitlab.com';
166165
$url = 'https://api.gitlab.com/';
167166
$auth = [
@@ -181,11 +180,9 @@ public function testAddAuthenticationHeaderWithGitlabPrivateToken(string $passwo
181180
->with('Using GitLab private token authentication', true, IOInterface::DEBUG);
182181

183182
$expectedHeaders = array_merge($headers, ['PRIVATE-TOKEN: ' . $auth['username']]);
183+
$options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
184184

185-
self::assertSame(
186-
$expectedHeaders,
187-
$this->authHelper->addAuthenticationHeader($headers, $origin, $url)
188-
);
185+
self::assertSame($expectedHeaders, $options['http']['header']);
189186
}
190187

191188
public function testAddAuthenticationHeaderWithBitbucketOathToken(): void
@@ -194,6 +191,7 @@ public function testAddAuthenticationHeaderWithBitbucketOathToken(): void
194191
'Accept-Encoding: gzip',
195192
'Connection: close',
196193
];
194+
$options = ['http' => ['header' => $headers]];
197195
$origin = 'bitbucket.org';
198196
$url = 'https://bitbucket.org/site/oauth2/authorize';
199197
$auth = [
@@ -208,11 +206,9 @@ public function testAddAuthenticationHeaderWithBitbucketOathToken(): void
208206
->with('Using Bitbucket OAuth token authentication', true, IOInterface::DEBUG);
209207

210208
$expectedHeaders = array_merge($headers, ['Authorization: Bearer ' . $auth['password']]);
209+
$options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
211210

212-
self::assertSame(
213-
$expectedHeaders,
214-
$this->authHelper->addAuthenticationHeader($headers, $origin, $url)
215-
);
211+
self::assertSame($expectedHeaders, $options['http']['header']);
216212
}
217213

218214
public static function bitbucketPublicUrlProvider(): array
@@ -232,6 +228,7 @@ public function testAddAuthenticationHeaderWithBitbucketPublicUrl(string $url):
232228
'Accept-Encoding: gzip',
233229
'Connection: close',
234230
];
231+
$options = ['http' => ['header' => $headers]];
235232
$origin = 'bitbucket.org';
236233
$auth = [
237234
'username' => 'x-token-auth',
@@ -240,10 +237,8 @@ public function testAddAuthenticationHeaderWithBitbucketPublicUrl(string $url):
240237

241238
$this->expectsAuthentication($origin, $auth);
242239

243-
self::assertSame(
244-
$headers,
245-
$this->authHelper->addAuthenticationHeader($headers, $origin, $url)
246-
);
240+
$options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
241+
self::assertSame($headers, $options['http']['header']);
247242
}
248243

249244
public static function basicHttpAuthenticationProvider(): array
@@ -289,6 +284,7 @@ public function testAddAuthenticationHeaderWithBasicHttpAuthentication(string $u
289284
'Accept-Encoding: gzip',
290285
'Connection: close',
291286
];
287+
$options = ['http' => ['header' => $headers]];
292288

293289
$this->expectsAuthentication($origin, $auth);
294290

@@ -305,10 +301,9 @@ public function testAddAuthenticationHeaderWithBasicHttpAuthentication(string $u
305301
['Authorization: Basic ' . base64_encode($auth['username'] . ':' . $auth['password'])]
306302
);
307303

308-
self::assertSame(
309-
$expectedHeaders,
310-
$this->authHelper->addAuthenticationHeader($headers, $origin, $url)
311-
);
304+
$options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
305+
306+
self::assertSame($expectedHeaders, $options['http']['header']);
312307
}
313308

314309
/**
@@ -625,6 +620,60 @@ function ($repositoryName) use (&$getAuthenticationReturnValues) {
625620
);
626621
}
627622

623+
/**
624+
* @dataProvider basicHttpAuthenticationProvider
625+
* @param array<string, string|null> $auth
626+
* @phpstan-param array{username: string|null, password: string|null} $auth
627+
*/
628+
public function testAddAuthenticationHeaderIsWorking(string $url, string $origin, array $auth): void
629+
{
630+
set_error_handler(
631+
static function (): bool {
632+
return true;
633+
},
634+
E_USER_DEPRECATED
635+
);
636+
637+
$this->expectsAuthentication($origin, $auth);
638+
$headers = [
639+
'Accept-Encoding: gzip',
640+
'Connection: close',
641+
];
642+
643+
$this->expectsAuthentication($origin, $auth);
644+
645+
try {
646+
$updatedHeaders = $this->authHelper->addAuthenticationHeader($headers, $origin, $url);
647+
} finally {
648+
restore_error_handler();
649+
}
650+
$this->assertIsArray($updatedHeaders);
651+
652+
653+
}
654+
655+
public function testAddAuthenticationHeaderDeprecation(): void
656+
{
657+
set_error_handler(
658+
static function (int $errno, string $errstr) {
659+
throw new \RuntimeException($errstr);
660+
},
661+
E_USER_DEPRECATED
662+
);
663+
664+
$headers = [];
665+
$origin = 'example.org';
666+
$url = 'file://' . __FILE__;
667+
668+
669+
$expectedException = new \RuntimeException('AuthHelper::addAuthenticationHeader is deprecated since Composer 2.9 use addAuthenticationOptions instead.');
670+
$this->expectExceptionObject($expectedException);
671+
try {
672+
$this->authHelper->addAuthenticationHeader($headers, $origin, $url);
673+
} finally {
674+
restore_error_handler();
675+
}
676+
}
628677
/**
629678
* @param array<string, string|null> $auth
630679
*

0 commit comments

Comments
 (0)