@@ -16,6 +16,7 @@ internal sealed class AccountDriver : IDisposable
1616 private readonly ITestOutputHelper _testOutputHelper ;
1717 private readonly IMessaging _messaging ;
1818 private readonly HttpClient _oauthClient ;
19+ private readonly HttpClient _httpClient ;
1920
2021 public AccountDriver ( ITestOutputHelper testOutputHelper , HttpClient httpClient , IMessaging messaging , CookieContainer cookieContainer )
2122 {
@@ -31,10 +32,23 @@ public AccountDriver(ITestOutputHelper testOutputHelper, HttpClient httpClient,
3132 AllowAutoRedirect = false
3233 } ;
3334
35+ // Create a separate HttpClient for OAuth2.0 operations that doesn't auto-follow redirects
36+ var mainHttpHandler = new HttpClientHandler ( )
37+ {
38+ CookieContainer = cookieContainer ,
39+ UseCookies = true ,
40+ CheckCertificateRevocationList = true ,
41+ AllowAutoRedirect = true
42+ } ;
43+
3444 _oauthClient = new HttpClient ( oauthHandler , true )
3545 {
3646 BaseAddress = httpClient . BaseAddress
3747 } ;
48+ _httpClient = new HttpClient ( mainHttpHandler , true )
49+ {
50+ BaseAddress = httpClient . BaseAddress
51+ } ;
3852 }
3953
4054 public async Task < RegisterResponse ? > RegisterUser ( string emailAddress , string password )
@@ -71,8 +85,8 @@ public AccountDriver(ITestOutputHelper testOutputHelper, HttpClient httpClient,
7185 _testOutputHelper . WriteLine ( $ "Got registration page content, length: { pageContent . Length } ") ;
7286
7387 // Step 2: Extract all form fields, including hidden ones
74- var formFields = HtmlFormParser . ExtractFormFields ( pageContent ) ;
75- var antiForgeryToken = HtmlFormParser . ExtractAntiForgeryToken ( pageContent ) ;
88+ var formFields = new Dictionary < string , string > ( ) ;
89+ var antiForgeryToken = FormDataExtractor . ExtractAntiForgeryToken ( pageContent ) ;
7690
7791 _testOutputHelper . WriteLine ( $ "Extracted { formFields . Count } form fields") ;
7892
@@ -82,7 +96,7 @@ public AccountDriver(ITestOutputHelper testOutputHelper, HttpClient httpClient,
8296 _testOutputHelper . WriteLine ( "Added anti-forgery token" ) ;
8397 }
8498
85- // Step 3: Set the user registration data
99+ // Step 3: Set the user registration data
86100 formFields [ "Input.Email" ] = emailAddress ;
87101 formFields [ "Input.Password" ] = password ;
88102 formFields [ "Input.ConfirmPassword" ] = password ;
@@ -187,7 +201,9 @@ public AccountDriver(ITestOutputHelper testOutputHelper, HttpClient httpClient,
187201 // Step 4: Follow authorization flow using OAuth client (no auto-redirect)
188202 var authorizationResponse = await _oauthClient . GetAsync ( authorizationUrl ) ;
189203
190- if ( ! authorizationResponse . IsSuccessStatusCode )
204+ // The authorization response should return HttpStatusCode.Found (302) if successful, with the redirect location containing the authorization code.
205+ // In the 'Location' header
206+ if ( authorizationResponse . StatusCode != HttpStatusCode . Found )
191207 {
192208 _testOutputHelper . WriteLine ( $ "Authorization request failed: { authorizationResponse . StatusCode } ") ;
193209 var errorContent = await authorizationResponse . Content . ReadAsStringAsync ( ) ;
@@ -277,8 +293,8 @@ private async Task AuthenticateUserViaIdentityUI(string emailAddress, string pas
277293 var loginPageContent = await loginPageResponse . Content . ReadAsStringAsync ( ) ;
278294
279295 // Step 2: Extract form fields and anti-forgery token
280- var formFields = HtmlFormParser . ExtractFormFields ( loginPageContent ) ;
281- var antiForgeryToken = HtmlFormParser . ExtractAntiForgeryToken ( loginPageContent ) ;
296+ var formFields = new Dictionary < string , string > ( ) ;
297+ var antiForgeryToken = FormDataExtractor . ExtractAntiForgeryToken ( loginPageContent ) ;
282298
283299 if ( antiForgeryToken != null )
284300 {
@@ -341,12 +357,6 @@ private static string BuildAuthorizationUrl(string codeChallenge, string state)
341357 // If no direct redirect, check if we need to handle a consent form
342358 var responseContent = await response . Content . ReadAsStringAsync ( ) ;
343359
344- if ( IsConsentForm ( responseContent ) )
345- {
346- _testOutputHelper . WriteLine ( "Consent form detected, submitting consent" ) ;
347- return await HandleConsentForm ( responseContent , state ) ;
348- }
349-
350360 _testOutputHelper . WriteLine ( "No authorization code or consent form found in response" ) ;
351361 _testOutputHelper . WriteLine ( $ "Response status: { response . StatusCode } ") ;
352362 _testOutputHelper . WriteLine ( $ "Response content: { responseContent } ") ;
@@ -515,75 +525,10 @@ private static bool HasValidationErrors(string htmlContent)
515525 return false ;
516526 }
517527
518- private static bool IsConsentForm ( string htmlContent )
519- {
520- // Check for consent form indicators
521- return htmlContent . Contains ( "Allow this application to access" , StringComparison . OrdinalIgnoreCase ) ||
522- htmlContent . Contains ( "consent" , StringComparison . OrdinalIgnoreCase ) ||
523- htmlContent . Contains ( "Grant access" , StringComparison . OrdinalIgnoreCase ) ||
524- htmlContent . Contains ( "Authorize" , StringComparison . OrdinalIgnoreCase ) ||
525- htmlContent . Contains ( "name=\" submit.Allow\" " , StringComparison . OrdinalIgnoreCase ) ;
526- }
527-
528- private async Task < string ? > HandleConsentForm ( string consentFormHtml , string state )
529- {
530- try
531- {
532- // Extract form fields from the consent form
533- var formFields = HtmlFormParser . ExtractFormFields ( consentFormHtml ) ;
534- var formAction = HtmlFormParser . ExtractFormAction ( consentFormHtml ) ;
535- var antiForgeryToken = HtmlFormParser . ExtractAntiForgeryToken ( consentFormHtml ) ;
536-
537- if ( antiForgeryToken != null )
538- {
539- formFields [ "__RequestVerificationToken" ] = antiForgeryToken ;
540- }
541-
542- // Add consent approval
543- formFields [ "submit.Accept" ] = "Accept" ;
544- formFields . Remove ( "submit.Deny" ) ; // Remove deny if present
545-
546- // Determine the form action URL
547- var actionUrl = string . IsNullOrEmpty ( formAction ) ? TestConstants . AuthorizeEndpoint : formAction ;
548-
549- _testOutputHelper . WriteLine ( $ "Submitting consent form to: { actionUrl } ") ;
550-
551- // Submit the consent form using OAuth client (no auto-redirect)
552- using var consentContent = new FormUrlEncodedContent ( formFields ) ;
553- var consentResponse = await _oauthClient . PostAsync ( actionUrl , consentContent ) ;
554-
555- if ( consentResponse . StatusCode == HttpStatusCode . Redirect )
556- {
557- _testOutputHelper . WriteLine ( "Consent approved - got redirect response" ) ;
558- return await ExtractAuthorizationCode ( consentResponse ) ;
559- }
560-
561- var consentResponseContent = await consentResponse . Content . ReadAsStringAsync ( ) ;
562- _testOutputHelper . WriteLine ( $ "Unexpected consent response: { consentResponse . StatusCode } ") ;
563- _testOutputHelper . WriteLine ( $ "Content: { consentResponseContent } ") ;
564-
565- return null ;
566- }
567- catch ( HttpRequestException ex )
568- {
569- _testOutputHelper . WriteLine ( $ "HTTP error handling consent form: { ex . Message } ") ;
570- return null ;
571- }
572- catch ( InvalidOperationException ex )
573- {
574- _testOutputHelper . WriteLine ( $ "Invalid operation error handling consent form: { ex . Message } ") ;
575- return null ;
576- }
577- catch ( JsonException ex )
578- {
579- _testOutputHelper . WriteLine ( $ "JSON parsing error handling consent form: { ex . Message } ") ;
580- return null ;
581- }
582- }
583-
584528 public void Dispose ( )
585529 {
586530 _oauthClient ? . Dispose ( ) ;
531+ _httpClient ? . Dispose ( ) ;
587532 GC . SuppressFinalize ( this ) ;
588533 }
589534}
0 commit comments