Skip to content

Commit bae90d3

Browse files
committed
trace2: instrument authentication flows
Authentication spans browser, device-code, refresh, account selection, and provider-specific decisions that are otherwise indistinguishable in a trace. Add regions and mode data at those boundaries so delays and user-flow choices can be diagnosed without recording credentials. Assisted-by: GPT-5.6 Sol Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
1 parent c3433b1 commit bae90d3

3 files changed

Lines changed: 30 additions & 8 deletions

File tree

‎src/Atlassian.Bitbucket/BitbucketAuthentication.cs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ public BitbucketAuthentication(ICommandContext context, IRegistry<BitbucketOAuth
7272

7373
public async Task<CredentialsPromptResult> GetCredentialsAsync(Uri targetUri, string userName, AuthenticationModes modes)
7474
{
75+
using var _ = Trace2.StartRegion("bitbucket", "get_creds");
76+
7577
ThrowIfUserInteractionDisabled();
7678

7779
// If we don't have a desktop session/GUI then we cannot offer OAuth since the only
@@ -250,6 +252,8 @@ private async Task<CredentialsPromptResult> GetCredentialsViaHelperAsync(
250252

251253
public async Task<OAuth2TokenResult> CreateOAuthCredentialsAsync(GitRequest request)
252254
{
255+
using var _ = Trace2.StartRegion("bitbucket", "oauth_browser");
256+
253257
ThrowIfUserInteractionDisabled();
254258

255259
var browserOptions = new OAuth2WebBrowserOptions
@@ -267,6 +271,8 @@ public async Task<OAuth2TokenResult> CreateOAuthCredentialsAsync(GitRequest requ
267271

268272
public async Task<OAuth2TokenResult> RefreshOAuthCredentialsAsync(GitRequest request, string refreshToken)
269273
{
274+
using var _ = Trace2.StartRegion("bitbucket", "oauth_refresh");
275+
270276
var client = _oauth2ClientRegistry.Get(request);
271277
return await client.GetTokenByRefreshTokenAsync(refreshToken, CancellationToken.None);
272278
}

‎src/Core/Authentication/OAuth/OAuth2Client.cs‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ public IOAuth2CodeGenerator CodeGenerator
105105
public async Task<OAuth2AuthorizationCodeResult> GetAuthorizationCodeAsync(IEnumerable<string> scopes,
106106
IOAuth2WebBrowser browser, IDictionary<string, string> extraQueryParams, CancellationToken ct)
107107
{
108+
using IDisposable region = Trace2.StartRegion(OAuth2Constants.Trace2Category, "get_authcode");
109+
108110
string state = CodeGenerator.CreateNonce();
109111
string codeVerifier = CodeGenerator.CreatePkceCodeVerifier();
110112
string codeChallenge = CodeGenerator.CreatePkceCodeChallenge(OAuth2PkceChallengeMethod.Sha256, codeVerifier);
@@ -167,8 +169,11 @@ public async Task<OAuth2AuthorizationCodeResult> GetAuthorizationCodeAsync(IEnum
167169

168170
// Open the browser at the request URI to start the authorization code grant flow, and
169171
// intercept the response parameters delivered to the redirect URI.
170-
IDictionary<string, string> responseParams =
171-
await browser.GetAuthenticationResponseAsync(authorizationUri, redirectUri, _responseMode, ct);
172+
IDictionary<string, string> responseParams;
173+
using (Trace2.StartRegion(OAuth2Constants.Trace2Category, "browser"))
174+
{
175+
responseParams = await browser.GetAuthenticationResponseAsync(authorizationUri, redirectUri, _responseMode, ct);
176+
}
172177

173178
// Check for errors serious enough we should terminate the flow, such as if the state value returned does
174179
// not match the one we passed. This indicates a badly implemented Authorization Server, or worse, some
@@ -196,8 +201,7 @@ public async Task<OAuth2AuthorizationCodeResult> GetAuthorizationCodeAsync(IEnum
196201

197202
public async Task<OAuth2DeviceCodeResult> GetDeviceCodeAsync(IEnumerable<string> scopes, CancellationToken ct)
198203
{
199-
var label = "get device code";
200-
using IDisposable region = Trace2.StartRegion(OAuth2Constants.Trace2Category, label);
204+
using IDisposable region = Trace2.StartRegion(OAuth2Constants.Trace2Category, "get_devicecode");
201205

202206
if (_endpoints.DeviceAuthorizationEndpoint is null)
203207
{
@@ -234,8 +238,7 @@ public async Task<OAuth2DeviceCodeResult> GetDeviceCodeAsync(IEnumerable<string>
234238

235239
public async Task<OAuth2TokenResult> GetTokenByAuthorizationCodeAsync(OAuth2AuthorizationCodeResult authorizationCodeResult, CancellationToken ct)
236240
{
237-
var label = "get token by auth code";
238-
using IDisposable region = Trace2.StartRegion(OAuth2Constants.Trace2Category, label);
241+
using IDisposable region = Trace2.StartRegion(OAuth2Constants.Trace2Category, "token_by_authcode");
239242

240243
var formData = new Dictionary<string, string>
241244
{
@@ -273,8 +276,7 @@ public async Task<OAuth2TokenResult> GetTokenByAuthorizationCodeAsync(OAuth2Auth
273276

274277
public async Task<OAuth2TokenResult> GetTokenByRefreshTokenAsync(string refreshToken, CancellationToken ct)
275278
{
276-
var label = "get token by refresh token";
277-
using IDisposable region = Trace2.StartRegion(OAuth2Constants.Trace2Category, label);
279+
using IDisposable region = Trace2.StartRegion(OAuth2Constants.Trace2Category, "token_by_refresh");
278280

279281
var formData = new Dictionary<string, string>
280282
{
@@ -306,6 +308,8 @@ public async Task<OAuth2TokenResult> GetTokenByRefreshTokenAsync(string refreshT
306308

307309
public async Task<OAuth2TokenResult> GetTokenByDeviceCodeAsync(OAuth2DeviceCodeResult deviceCodeResult, CancellationToken ct)
308310
{
311+
using IDisposable region = Trace2.StartRegion(OAuth2Constants.Trace2Category, "token_by_devicecode");
312+
309313
var formData = new Dictionary<string, string>
310314
{
311315
[OAuth2Constants.DeviceAuthorization.GrantTypeParameter] = OAuth2Constants.DeviceAuthorization.DeviceCodeGrantType,

‎src/GitHub/GitHubAuthentication.cs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public GitHubAuthentication(ICommandContext context)
7272

7373
public async Task<string> SelectAccountAsync(Uri targetUri, IEnumerable<string> accounts)
7474
{
75+
using var _ = Trace2.StartRegion("github", "select_account");
7576
ThrowIfUserInteractionDisabled();
7677

7778
if (Context.Settings.IsGuiPromptsEnabled && Context.SessionManager.IsDesktopSession)
@@ -135,12 +136,17 @@ public async Task<string> SelectAccountAsync(Uri targetUri, IEnumerable<string>
135136

136137
public async Task<AuthenticationPromptResult> GetAuthenticationAsync(Uri targetUri, string userName, AuthenticationModes modes)
137138
{
139+
using var _ = Trace2.StartRegion("github", "get_auth");
140+
Trace2.WriteData("github", "modes/initial", modes.ToString());
141+
138142
// If we cannot start a browser then don't offer the option
139143
if (!Context.SessionManager.IsWebBrowserAvailable)
140144
{
141145
modes = modes & ~AuthenticationModes.Browser;
142146
}
143147

148+
Trace2.WriteData("github", "modes/available", modes.ToString());
149+
144150
// We need at least one mode!
145151
if (modes == AuthenticationModes.None)
146152
{
@@ -348,6 +354,8 @@ private async Task<AuthenticationPromptResult> GetAuthenticationViaHelperAsync(
348354

349355
public async Task<string> GetTwoFactorCodeAsync(Uri targetUri, bool isSms)
350356
{
357+
using var _ = Trace2.StartRegion("github", "get_tfa");
358+
351359
ThrowIfUserInteractionDisabled();
352360

353361
if (Context.Settings.IsGuiPromptsEnabled && Context.SessionManager.IsDesktopSession)
@@ -408,6 +416,8 @@ private async Task<string> GetTwoFactorCodeViaHelperAsync(bool isSms, string arg
408416

409417
public async Task<OAuth2TokenResult> GetOAuthTokenViaBrowserAsync(Uri targetUri, IEnumerable<string> scopes, string loginHint)
410418
{
419+
using var _ = Trace2.StartRegion("github", "oauth_browser");
420+
411421
ThrowIfUserInteractionDisabled();
412422

413423
var oauthClient = new GitHubOAuth2Client(HttpClient, Context.Settings, targetUri);
@@ -447,6 +457,8 @@ public async Task<OAuth2TokenResult> GetOAuthTokenViaBrowserAsync(Uri targetUri,
447457

448458
public async Task<OAuth2TokenResult> GetOAuthTokenViaDeviceCodeAsync(Uri targetUri, IEnumerable<string> scopes)
449459
{
460+
using var _ = Trace2.StartRegion("github", "oauth_device_code");
461+
450462
ThrowIfUserInteractionDisabled();
451463

452464
var oauthClient = new GitHubOAuth2Client(HttpClient, Context.Settings, targetUri);

0 commit comments

Comments
 (0)