66using UniGetUI . Core . SecureSettings ;
77using UniGetUI . Core . SettingsEngine ;
88using Windows . System ;
9+ using UniGetUI . Interface ;
910
1011namespace UniGetUI . Services
1112{
1213 public class GitHubAuthService
1314 {
1415 private readonly string GitHubClientId = Secrets . GetGitHubClientId ( ) ;
1516 private readonly string GitHubClientSecret = Secrets . GetGitHubClientSecret ( ) ;
16-
17- private const string DataReceivedWebsite = """
18- <html>
19- <style>
20- div {
21- display: flex;
22- flex-direction: column;
23- align-items: center;
24- justify-content: center;
25- height: 100vh;
26- font-family: sans-serif;
27- text-align: center;
28- }
29- </style>
30- <script>
31- window.close();
32- </script>
33- <div>
34- <title>UniGetUI authentication</title>
35- <h1>Authentication successful</h1>
36- <p>You can now close this window and return to UniGetUI</p>
37- </div>
38- </html>
39- """ ;
40-
4117 private const string RedirectUri = "http://127.0.0.1:58642/" ;
42-
4318 private readonly GitHubClient _client ;
4419
4520 public static event EventHandler < EventArgs > ? AuthStatusChanged ;
@@ -63,25 +38,13 @@ public GitHubAuthService()
6338 } ;
6439 }
6540
66- private static HttpListener ? httpListener ;
41+ private GHAuthApiRunner ? loginBackend ;
6742 public async Task < bool > SignInAsync ( )
6843 {
6944 try
7045 {
7146 Logger . Info ( "Initiating GitHub sign-in process using loopback redirect..." ) ;
7247
73- if ( httpListener is null )
74- {
75- httpListener = new HttpListener ( ) ;
76- httpListener . Prefixes . Add ( RedirectUri ) ;
77- httpListener . Start ( ) ;
78- Logger . Info ( $ "Listening for GitHub callback on { RedirectUri } ") ;
79- }
80- else
81- {
82- Logger . Warn ( "Http listener already existed" ) ;
83- }
84-
8548 var request = new OauthLoginRequest ( GitHubClientId )
8649 {
8750 Scopes = { "read:user" , "gist" } ,
@@ -90,41 +53,33 @@ public async Task<bool> SignInAsync()
9053
9154 var oauthLoginUrl = _client . Oauth . GetGitHubLoginUrl ( request ) ;
9255
56+ codeFromAPI = null ;
57+ if ( loginBackend is not null )
58+ {
59+ try
60+ {
61+ await loginBackend . Stop ( ) ;
62+ loginBackend . Dispose ( ) ;
63+ loginBackend = null ;
64+ }
65+ catch ( Exception ex )
66+ {
67+ Logger . Warn ( ex ) ;
68+ }
69+ }
70+ loginBackend = new GHAuthApiRunner ( ) ;
71+ loginBackend . OnLogin += BackgroundApiOnOnLogin ;
72+ await loginBackend . Start ( ) ;
9373 await Launcher . LaunchUriAsync ( oauthLoginUrl ) ;
9474
95- var context = await httpListener . GetContextAsync ( ) ;
96-
97- var response = context . Response ;
98- var buffer = Encoding . UTF8 . GetBytes ( DataReceivedWebsite ) ;
99- response . ContentLength64 = buffer . Length ;
100- var output = response . OutputStream ;
101- await output . WriteAsync ( buffer , 0 , buffer . Length ) ;
102- output . Close ( ) ;
103-
104- httpListener . Stop ( ) ;
105- httpListener = null ;
106- Logger . Info ( "GitHub callback received and processed." ) ;
75+ while ( codeFromAPI is null ) await Task . Delay ( 100 ) ;
10776
108- var code = context . Request . QueryString [ "code" ] ;
109- if ( string . IsNullOrEmpty ( code ) )
110- {
111- var error = context . Request . QueryString [ "error" ] ;
112- var errorDescription = context . Request . QueryString [ "error_description" ] ;
113- Logger . Error ( $ "GitHub OAuth callback returned an error: { error } - { errorDescription } ") ;
114- AuthStatusChanged ? . Invoke ( this , EventArgs . Empty ) ;
115- return false ;
116- }
77+ loginBackend . OnLogin -= BackgroundApiOnOnLogin ;
78+ await loginBackend . Stop ( ) ;
79+ loginBackend . Dispose ( ) ;
80+ loginBackend = null ;
11781
118- return await _completeSignInAsync ( code ) ;
119- }
120- catch ( HttpListenerException ex ) when ( ex . ErrorCode == 5 ) // Access Denied
121- {
122- Logger . Error ( "Access denied to the http listener. Please run the following command in an administrator terminal:" ) ;
123- Logger . Error ( $ "netsh http add urlacl url={ RedirectUri } user=Everyone") ;
124- // Optionally, you could try to run this command for the user.
125- // For now, just logging the instruction.
126- AuthStatusChanged ? . Invoke ( this , EventArgs . Empty ) ;
127- return false ;
82+ return await _completeSignInAsync ( codeFromAPI ) ;
12883 }
12984 catch ( Exception ex )
13085 {
@@ -134,13 +89,12 @@ public async Task<bool> SignInAsync()
13489 AuthStatusChanged ? . Invoke ( this , EventArgs . Empty ) ;
13590 return false ;
13691 }
137- finally
138- {
139- try {
140- httpListener ? . Stop ( ) ;
141- } catch { /* ignore */ }
142- httpListener = null ;
143- }
92+ }
93+
94+ private string ? codeFromAPI ;
95+ private void BackgroundApiOnOnLogin ( object ? sender , string c )
96+ {
97+ codeFromAPI = c ;
14498 }
14599
146100 private async Task < bool > _completeSignInAsync ( string code )
0 commit comments