@@ -77,19 +77,19 @@ private record TokenResponse(string? token, string? access_token, int? expires_i
77
77
/// Credentials for the request are retrieved from the credential provider, then used to acquire a token.
78
78
/// That token is cached for some duration on a per-host basis.
79
79
/// </summary>
80
- /// <param name="realm "></param>
80
+ /// <param name="uri "></param>
81
81
/// <param name="service"></param>
82
82
/// <param name="scope"></param>
83
83
/// <param name="cancellationToken"></param>
84
84
/// <returns></returns>
85
- private async Task < AuthenticationHeaderValue ? > GetAuthenticationAsync ( string scheme , Uri realm , string service , string ? scope , CancellationToken cancellationToken )
85
+ private async Task < AuthenticationHeaderValue ? > GetAuthenticationAsync ( string scheme , Uri uri , string service , string ? scope , CancellationToken cancellationToken )
86
86
{
87
87
// Allow overrides for auth via environment variables
88
88
string ? credU = Environment . GetEnvironmentVariable ( ContainerHelpers . HostObjectUser ) ;
89
89
string ? credP = Environment . GetEnvironmentVariable ( ContainerHelpers . HostObjectPass ) ;
90
90
91
91
// fetch creds for the host
92
- DockerCredentials ? privateRepoCreds ;
92
+ DockerCredentials ? privateRepoCreds ;
93
93
94
94
if ( ! string . IsNullOrEmpty ( credU ) && ! string . IsNullOrEmpty ( credP ) )
95
95
{
@@ -99,26 +99,26 @@ private record TokenResponse(string? token, string? access_token, int? expires_i
99
99
{
100
100
try
101
101
{
102
- privateRepoCreds = await CredsProvider . GetCredentialsAsync ( realm . Host ) ;
102
+ privateRepoCreds = await CredsProvider . GetCredentialsAsync ( uri . Host ) ;
103
103
}
104
104
catch ( Exception e )
105
105
{
106
- throw new CredentialRetrievalException ( realm . Host , e ) ;
106
+ throw new CredentialRetrievalException ( uri . Host , e ) ;
107
107
}
108
108
}
109
109
110
110
if ( scheme is "Basic" )
111
111
{
112
112
var basicAuth = new AuthenticationHeaderValue ( "Basic" , Convert . ToBase64String ( Encoding . ASCII . GetBytes ( $ "{ privateRepoCreds . Username } :{ privateRepoCreds . Password } ") ) ) ;
113
- return basicAuth ;
113
+ return AuthHeaderCache . AddOrUpdate ( uri , basicAuth ) ;
114
114
}
115
115
else if ( scheme is "Bearer" )
116
116
{
117
117
// use those creds when calling the token provider
118
118
var header = privateRepoCreds . Username == "<token>"
119
119
? new AuthenticationHeaderValue ( "Bearer" , privateRepoCreds . Password )
120
120
: new AuthenticationHeaderValue ( "Basic" , Convert . ToBase64String ( Encoding . ASCII . GetBytes ( $ "{ privateRepoCreds . Username } :{ privateRepoCreds . Password } ") ) ) ;
121
- var builder = new UriBuilder ( realm ) ;
121
+ var builder = new UriBuilder ( uri ) ;
122
122
var queryDict = System . Web . HttpUtility . ParseQueryString ( "" ) ;
123
123
queryDict [ "service" ] = service ;
124
124
if ( scope is string s )
@@ -140,7 +140,7 @@ private record TokenResponse(string? token, string? access_token, int? expires_i
140
140
141
141
// save the retrieved token in the cache
142
142
var bearerAuth = new AuthenticationHeaderValue ( "Bearer" , token . ResolvedToken ) ;
143
- return bearerAuth ;
143
+ return AuthHeaderCache . AddOrUpdate ( uri , bearerAuth ) ;
144
144
}
145
145
else
146
146
{
@@ -155,7 +155,11 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
155
155
throw new ArgumentException ( "No RequestUri specified" , nameof ( request ) ) ;
156
156
}
157
157
158
- // TODO: attempt to use cached token for the request if available
158
+ // attempt to use cached token for the request if available
159
+ if ( AuthHeaderCache . TryGet ( request . RequestUri , out AuthenticationHeaderValue ? cachedAuthentication ) )
160
+ {
161
+ request . Headers . Authorization = cachedAuthentication ;
162
+ }
159
163
160
164
var response = await base . SendAsync ( request , cancellationToken ) ;
161
165
if ( response is { StatusCode : HttpStatusCode . OK } )
@@ -166,7 +170,7 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
166
170
{
167
171
if ( await GetAuthenticationAsync ( scheme , authInfo . Realm , authInfo . Service , authInfo . Scope , cancellationToken ) is AuthenticationHeaderValue authentication )
168
172
{
169
- request . Headers . Authorization = authentication ;
173
+ request . Headers . Authorization = AuthHeaderCache . AddOrUpdate ( request . RequestUri , authentication ) ;
170
174
return await base . SendAsync ( request , cancellationToken ) ;
171
175
}
172
176
return response ;
0 commit comments