@@ -71,18 +71,19 @@ private static bool TryParseAuthenticationInfo(HttpResponseMessage msg, [NotNull
71
71
if ( header . Scheme is not null )
72
72
{
73
73
scheme = header . Scheme ;
74
- var keyValues = ParseBearerArgs ( header . Parameter ) ;
75
- if ( keyValues is null )
76
- {
77
- return false ;
78
- }
79
74
80
75
if ( header . Scheme . Equals ( BasicAuthScheme , StringComparison . OrdinalIgnoreCase ) )
81
76
{
82
- return TryParseBasicAuthInfo ( keyValues , msg . RequestMessage ! . RequestUri ! , out bearerAuthInfo ) ;
77
+ bearerAuthInfo = null ;
78
+ return true ;
83
79
}
84
80
else if ( header . Scheme . Equals ( BearerAuthScheme , StringComparison . OrdinalIgnoreCase ) )
85
81
{
82
+ var keyValues = ParseBearerArgs ( header . Parameter ) ;
83
+ if ( keyValues is null )
84
+ {
85
+ return false ;
86
+ }
86
87
return TryParseBearerAuthInfo ( keyValues , out bearerAuthInfo ) ;
87
88
}
88
89
else
@@ -110,12 +111,6 @@ static bool TryParseBearerAuthInfo(Dictionary<string, string> authValues, [NotNu
110
111
}
111
112
}
112
113
113
- static bool TryParseBasicAuthInfo ( Dictionary < string , string > authValues , Uri requestUri , out AuthInfo ? authInfo )
114
- {
115
- authInfo = null ;
116
- return true ;
117
- }
118
-
119
114
static Dictionary < string , string > ? ParseBearerArgs ( string ? bearerHeaderArgs )
120
115
{
121
116
if ( bearerHeaderArgs is null )
@@ -159,7 +154,6 @@ public DateTimeOffset ResolvedExpiration
159
154
/// </summary>
160
155
private async Task < ( AuthenticationHeaderValue , DateTimeOffset ) ? > GetAuthenticationAsync ( string registry , string scheme , AuthInfo ? bearerAuthInfo , CancellationToken cancellationToken )
161
156
{
162
-
163
157
DockerCredentials ? privateRepoCreds ;
164
158
// Allow overrides for auth via environment variables
165
159
if ( GetDockerCredentialsFromEnvironment ( _registryMode ) is ( string credU , string credP ) )
@@ -180,14 +174,20 @@ public DateTimeOffset ResolvedExpiration
180
174
{
181
175
Debug . Assert ( bearerAuthInfo is not null ) ;
182
176
183
- var authenticationValueAndDuration = await TryOAuthPostAsync ( privateRepoCreds , bearerAuthInfo , cancellationToken ) . ConfigureAwait ( false ) ;
184
- if ( authenticationValueAndDuration is not null )
177
+ // Obtain a Bearer token, when the credentials are:
178
+ // - an identity token: use it for OAuth
179
+ // - a username/password: use them for Basic auth, and fall back to OAuth
180
+
181
+ if ( string . IsNullOrWhiteSpace ( privateRepoCreds . IdentityToken ) )
185
182
{
186
- return authenticationValueAndDuration ;
183
+ var authenticationValueAndDuration = await TryTokenGetAsync ( privateRepoCreds , bearerAuthInfo , cancellationToken ) . ConfigureAwait ( false ) ;
184
+ if ( authenticationValueAndDuration is not null )
185
+ {
186
+ return authenticationValueAndDuration ;
187
+ }
187
188
}
188
189
189
- authenticationValueAndDuration = await TryTokenGetAsync ( privateRepoCreds , bearerAuthInfo , cancellationToken ) . ConfigureAwait ( false ) ;
190
- return authenticationValueAndDuration ;
190
+ return await TryOAuthPostAsync ( privateRepoCreds , bearerAuthInfo , cancellationToken ) . ConfigureAwait ( false ) ;
191
191
}
192
192
else
193
193
{
@@ -293,8 +293,7 @@ internal static (string credU, string credP)? GetDockerCredentialsFromEnvironmen
293
293
if ( ! postResponse . IsSuccessStatusCode )
294
294
{
295
295
await postResponse . LogHttpResponseAsync ( _logger , cancellationToken ) . ConfigureAwait ( false ) ;
296
- //return null to try HTTP GET instead
297
- return null ;
296
+ return null ; // try next method
298
297
}
299
298
_logger . LogTrace ( "Received '{statuscode}'." , postResponse . StatusCode ) ;
300
299
TokenResponse ? tokenResponse = JsonSerializer . Deserialize < TokenResponse > ( postResponse . Content . ReadAsStream ( cancellationToken ) ) ;
@@ -306,8 +305,7 @@ internal static (string credU, string credP)? GetDockerCredentialsFromEnvironmen
306
305
else
307
306
{
308
307
_logger . LogTrace ( Resource . GetString ( nameof ( Strings . CouldntDeserializeJsonToken ) ) ) ;
309
- // logging and returning null to try HTTP GET instead
310
- return null ;
308
+ return null ; // try next method
311
309
}
312
310
}
313
311
@@ -318,9 +316,7 @@ internal static (string credU, string credP)? GetDockerCredentialsFromEnvironmen
318
316
{
319
317
// this doesn't seem to be called out in the spec, but actual username/password auth information should be converted into Basic auth here,
320
318
// even though the overall Scheme we're authenticating for is Bearer
321
- var header = privateRepoCreds . Username == "<token>"
322
- ? new AuthenticationHeaderValue ( BearerAuthScheme , privateRepoCreds . Password )
323
- : new AuthenticationHeaderValue ( BasicAuthScheme , Convert . ToBase64String ( Encoding . ASCII . GetBytes ( $ "{ privateRepoCreds . Username } :{ privateRepoCreds . Password } ") ) ) ;
319
+ var header = new AuthenticationHeaderValue ( BasicAuthScheme , Convert . ToBase64String ( Encoding . ASCII . GetBytes ( $ "{ privateRepoCreds . Username } :{ privateRepoCreds . Password } ") ) ) ;
324
320
var builder = new UriBuilder ( new Uri ( bearerAuthInfo . Realm ) ) ;
325
321
326
322
_logger . LogTrace ( "Attempting to authenticate on {uri} using GET." , bearerAuthInfo . Realm ) ;
@@ -340,7 +336,8 @@ internal static (string credU, string credP)? GetDockerCredentialsFromEnvironmen
340
336
using var tokenResponse = await base . SendAsync ( message , cancellationToken ) . ConfigureAwait ( false ) ;
341
337
if ( ! tokenResponse . IsSuccessStatusCode )
342
338
{
343
- throw new UnableToAccessRepositoryException ( _registryName ) ;
339
+ await tokenResponse . LogHttpResponseAsync ( _logger , cancellationToken ) . ConfigureAwait ( false ) ;
340
+ return null ; // try next method
344
341
}
345
342
346
343
TokenResponse ? token = JsonSerializer . Deserialize < TokenResponse > ( tokenResponse . Content . ReadAsStream ( cancellationToken ) ) ;
@@ -412,7 +409,8 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
412
409
request . Headers . Authorization = authHeader ;
413
410
return await base . SendAsync ( request , cancellationToken ) . ConfigureAwait ( false ) ;
414
411
}
415
- return response ;
412
+
413
+ throw new UnableToAccessRepositoryException ( _registryName ) ;
416
414
}
417
415
else
418
416
{
0 commit comments