Skip to content

Commit 2538766

Browse files
committed
tinker
1 parent d8ed4f2 commit 2538766

File tree

1 file changed

+33
-34
lines changed

1 file changed

+33
-34
lines changed

src/shared/GitLab/GitLabHostProvider.cs

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,6 @@ public override bool IsSupported(HttpResponseMessage response)
8383
return response.Headers.Contains("X-Gitlab-Feature-Category");
8484
}
8585

86-
public override string GetServiceName(InputArguments input)
87-
{
88-
var baseUri = new Uri(base.GetServiceName(input));
89-
90-
string url = baseUri.AbsoluteUri;
91-
92-
// Trim trailing slash
93-
return url.TrimEnd('/');
94-
}
95-
9686
public override async Task<ICredential> GenerateCredentialAsync(InputArguments input)
9787
{
9888
ThrowIfDisposed();
@@ -152,44 +142,46 @@ internal AuthenticationModes GetSupportedAuthenticationModes(Uri targetUri)
152142
return AuthenticationModes.Basic | AuthenticationModes.Pat;
153143
}
154144

145+
// <remarks>Stores OAuth refresh token as a side effect</remarks>
155146
public override async Task<ICredential> GetCredentialAsync(InputArguments input)
156147
{
157148
ICredential credential = await base.GetCredentialAsync(input);
158-
if (credential.Account == "oauth2")
149+
if (credential.Account == "oauth2" && credential is not OAuthCredential)
159150
{
160-
// cast succeeds if and only if credential is freshly generated (not retrieved)
161-
OAuthCredential oAuthCredential = credential as OAuthCredential;
162-
if (oAuthCredential == null)
151+
Context.Trace.WriteLine("Retrieved stored OAuth credential");
152+
// retrieved OAuth credential may have expired, so refresh
153+
try
154+
{
155+
credential = await RefreshOAuthCredentialAsync(input);
156+
}
157+
catch (Exception e)
163158
{
164-
// retrieved OAuth credential may have expired, so refresh
165-
try
166-
{
167-
oAuthCredential = await RefreshOAuthCredentialAsync(input);
168-
}
169-
catch (Exception e)
170-
{
171-
Context.Terminal.WriteLine($"OAuth token refresh failed: {e.Message}");
172-
return credential;
173-
}
159+
Context.Terminal.WriteLine($"OAuth token refresh failed: {e.Message}");
174160
}
161+
}
162+
if (credential is OAuthCredential oAuthCredential)
163+
{
175164
// store refresh token under a separate service
176-
Context.Trace.WriteLine("Storing refresh token...");
177-
Context.CredentialStore.AddOrUpdate(GetRefreshTokenServiceName(input.GetRemoteUri()), "oauth2", oAuthCredential.RefreshToken);
178-
return oAuthCredential;
165+
string refreshTokenService = GetRefreshTokenServiceName(input);
166+
Context.Trace.WriteLine($"Storing credential with service={refreshTokenService} account={input.UserName}...");
167+
Context.CredentialStore.AddOrUpdate(refreshTokenService, oAuthCredential.Account, oAuthCredential.RefreshToken);
179168
}
180-
181169
return credential;
182170
}
183171

184-
internal class OAuthCredential : GitCredential
172+
internal class OAuthCredential : ICredential
185173
{
186-
// username must be oauth2 https://gitlab.com/gitlab-org/gitlab/-/issues/349461
187-
public OAuthCredential(OAuth2TokenResult oAuth2TokenResult) : base("oauth2", oAuth2TokenResult.AccessToken)
174+
public OAuthCredential(OAuth2TokenResult oAuth2TokenResult)
188175
{
176+
AccessToken = oAuth2TokenResult.AccessToken;
189177
RefreshToken = oAuth2TokenResult.RefreshToken;
190178
}
191179

180+
// username must be 'oauth2' https://gitlab.com/gitlab-org/gitlab/-/issues/349461
181+
public string Account => "oauth2";
182+
public string AccessToken { get; }
192183
public string RefreshToken { get; }
184+
string ICredential.Password => AccessToken;
193185
}
194186

195187
private async Task<OAuthCredential> GenerateOAuthCredentialAsync(InputArguments input)
@@ -202,7 +194,7 @@ private async Task<OAuthCredential> RefreshOAuthCredentialAsync(InputArguments i
202194
{
203195
// retrieve refresh token stored under separate service
204196
Context.Trace.WriteLine($"Checking for stored refresh token...");
205-
string refreshTokenServiceName = GetRefreshTokenServiceName(input.GetRemoteUri());
197+
string refreshTokenServiceName = GetRefreshTokenServiceName(input);
206198
string refreshToken = Context.CredentialStore.Get(refreshTokenServiceName, "oauth2").Password;
207199
if (refreshToken == null)
208200
{
@@ -218,9 +210,16 @@ protected override void ReleaseManagedResources()
218210
base.ReleaseManagedResources();
219211
}
220212

221-
private static string GetRefreshTokenServiceName(Uri baseUri)
213+
private string GetRefreshTokenServiceName(InputArguments input)
214+
{
215+
return new Uri(new Uri(GetServiceName(input)), "/refresh_token").AbsoluteUri;
216+
}
217+
218+
public override Task EraseCredentialAsync(InputArguments input)
222219
{
223-
return new Uri(baseUri.WithoutUserInfo(), "/refresh_token").AbsoluteUri;
220+
Context.CredentialStore.Remove(GetServiceName(input), input.UserName);
221+
Context.CredentialStore.Remove(GetRefreshTokenServiceName(input), "oauth2");
222+
return Task.CompletedTask;
224223
}
225224
}
226225
}

0 commit comments

Comments
 (0)