@@ -128,6 +128,33 @@ private async Task<ICredential> GetOAuthAccessToken(Uri remoteUri, string userNa
128128 Context . Trace ,
129129 config . UseAuthHeader ) ;
130130
131+ //
132+ // Prepend "refresh_token" to the hostname to get a (hopefully) unique service name that
133+ // doesn't clash with an existing credential service.
134+ //
135+ // Appending "/refresh_token" to the end of the remote URI may not always result in a unique
136+ // service because users may set credential.useHttpPath and include "/refresh_token" as a
137+ // path name.
138+ //
139+ string refreshService = new UriBuilder ( remoteUri ) { Host = $ "refresh_token.{ remoteUri . Host } " }
140+ . Uri . AbsoluteUri . TrimEnd ( '/' ) ;
141+
142+ // Try to use a refresh token if we have one
143+ ICredential refreshToken = Context . CredentialStore . Get ( refreshService , userName ) ;
144+ if ( refreshToken != null )
145+ {
146+ var refreshResult = await client . GetTokenByRefreshTokenAsync ( refreshToken . Password , CancellationToken . None ) ;
147+
148+ // Store new refresh token if we have been given one
149+ if ( ! string . IsNullOrWhiteSpace ( refreshResult . RefreshToken ) )
150+ {
151+ Context . CredentialStore . AddOrUpdate ( refreshService , refreshToken . Account , refreshToken . Password ) ;
152+ }
153+
154+ // Return the new access token
155+ return new GitCredential ( oauthUser , refreshResult . AccessToken ) ;
156+ }
157+
131158 // Determine which interactive OAuth mode to use. Start by checking for mode preference in config
132159 var supportedModes = OAuthAuthenticationModes . All ;
133160 if ( Context . Settings . TryGetSetting (
@@ -170,6 +197,12 @@ private async Task<ICredential> GetOAuthAccessToken(Uri remoteUri, string userNa
170197 throw new Exception ( "No authentication mode selected!" ) ;
171198 }
172199
200+ // Store the refresh token if we have one
201+ if ( ! string . IsNullOrWhiteSpace ( tokenResult . RefreshToken ) )
202+ {
203+ Context . CredentialStore . AddOrUpdate ( refreshService , oauthUser , tokenResult . RefreshToken ) ;
204+ }
205+
173206 return new GitCredential ( oauthUser , tokenResult . AccessToken ) ;
174207 }
175208
0 commit comments