@@ -21,12 +21,9 @@ class LoginManager : ILoginManager
21
21
{
22
22
private readonly ILogging logger = LogHelper . GetLogger < LoginManager > ( ) ;
23
23
24
- private readonly string [ ] scopes = { "user" , "repo" , "gist" , "write:public_key" } ;
25
24
private readonly IKeychain keychain ;
26
25
private readonly string clientId ;
27
26
private readonly string clientSecret ;
28
- private readonly string authorizationNote ;
29
- private readonly string fingerprint ;
30
27
private readonly IProcessManager processManager ;
31
28
private readonly ITaskManager taskManager ;
32
29
private readonly NPath nodeJsExecutablePath ;
@@ -38,8 +35,6 @@ class LoginManager : ILoginManager
38
35
/// <param name="keychain"></param>
39
36
/// <param name="clientId">The application's client API ID.</param>
40
37
/// <param name="clientSecret">The application's client API secret.</param>
41
- /// <param name="authorizationNote">An note to store with the authorization.</param>
42
- /// <param name="fingerprint">The machine fingerprint.</param>
43
38
/// <param name="processManager"></param>
44
39
/// <param name="taskManager"></param>
45
40
/// <param name="nodeJsExecutablePath"></param>
@@ -48,8 +43,6 @@ public LoginManager(
48
43
IKeychain keychain ,
49
44
string clientId ,
50
45
string clientSecret ,
51
- string authorizationNote = null ,
52
- string fingerprint = null ,
53
46
IProcessManager processManager = null , ITaskManager taskManager = null , NPath nodeJsExecutablePath = null , NPath octorunScript = null )
54
47
{
55
48
Guard . ArgumentNotNull ( keychain , nameof ( keychain ) ) ;
@@ -59,8 +52,6 @@ public LoginManager(
59
52
this . keychain = keychain ;
60
53
this . clientId = clientId ;
61
54
this . clientSecret = clientSecret ;
62
- this . authorizationNote = authorizationNote ;
63
- this . fingerprint = fingerprint ;
64
55
this . processManager = processManager ;
65
56
this . taskManager = taskManager ;
66
57
this . nodeJsExecutablePath = nodeJsExecutablePath ;
@@ -82,108 +73,59 @@ public async Task<LoginResultData> Login(
82
73
keychain . Connect ( host ) ;
83
74
keychain . SetCredentials ( new Credential ( host , username , password ) ) ;
84
75
85
- var newAuth = new NewAuthorization
86
- {
87
- Scopes = scopes ,
88
- Note = authorizationNote ,
89
- Fingerprint = fingerprint ,
90
- } ;
91
-
92
- ApplicationAuthorization auth = null ;
93
-
76
+ string token ;
94
77
try
95
78
{
96
- auth = await TryLogin ( host , username , password ) ;
97
- EnsureNonNullAuthorization ( auth ) ;
98
- }
99
- catch ( TwoFactorAuthorizationException e )
100
- {
101
- LoginResultCodes result ;
102
- if ( e is TwoFactorRequiredException )
79
+ token = await TryLogin ( host , username , password ) ;
80
+ if ( string . IsNullOrEmpty ( token ) )
103
81
{
104
- result = LoginResultCodes . CodeRequired ;
105
- logger . Trace ( "2FA TwoFactorAuthorizationException: {0} {1}" , LoginResultCodes . CodeRequired , e . Message ) ;
82
+ throw new InvalidOperationException ( "Returned token is null or empty" ) ;
106
83
}
107
- else
108
- {
109
- result = LoginResultCodes . CodeFailed ;
110
- logger . Error ( e , "2FA TwoFactorAuthorizationException: {0} {1}" , LoginResultCodes . CodeRequired , e . Message ) ;
111
- }
112
-
113
- return new LoginResultData ( result , e . Message , host , newAuth ) ;
114
- }
115
- catch ( LoginAttemptsExceededException e )
116
- {
117
- logger . Warning ( e , "Login LoginAttemptsExceededException: {0}" , e . Message ) ;
118
-
119
- await keychain . Clear ( host , false ) ;
120
- return new LoginResultData ( LoginResultCodes . LockedOut , Localization . LockedOut , host ) ;
121
84
}
122
- catch ( ApiValidationException e )
85
+ catch ( TwoFactorRequiredException e )
123
86
{
124
- logger . Warning ( e , "Login ApiValidationException: {0}" , e . Message ) ;
87
+ LoginResultCodes result ;
88
+ result = LoginResultCodes . CodeRequired ;
89
+ logger . Trace ( "2FA TwoFactorAuthorizationException: {0} {1}" , LoginResultCodes . CodeRequired , e . Message ) ;
125
90
126
- var message = e . ApiError . FirstErrorMessageSafe ( ) ;
127
- await keychain . Clear ( host , false ) ;
128
- return new LoginResultData ( LoginResultCodes . Failed , message , host ) ;
91
+ return new LoginResultData ( result , e . Message , host , password ) ;
129
92
}
130
93
catch ( Exception e )
131
94
{
132
95
logger . Warning ( e , "Login Exception" ) ;
133
96
134
- // Some enterprise instances don't support OAUTH, so fall back to using the
135
- // supplied password - on instances that don't support OAUTH the user should
136
- // be using a personal access token as the password.
137
- if ( EnterpriseWorkaround ( host , e ) )
138
- {
139
- auth = new ApplicationAuthorization ( password ) ;
140
- }
141
- else
142
- {
143
- await keychain . Clear ( host , false ) ;
144
- return new LoginResultData ( LoginResultCodes . Failed , Localization . LoginFailed , host ) ;
145
- }
97
+ await keychain . Clear ( host , false ) ;
98
+ return new LoginResultData ( LoginResultCodes . Failed , Localization . LoginFailed , host ) ;
146
99
}
147
100
148
- keychain . SetToken ( host , auth . Token ) ;
101
+ keychain . SetToken ( host , token ) ;
149
102
await keychain . Save ( host ) ;
150
103
151
104
return new LoginResultData ( LoginResultCodes . Success , "Success" , host ) ;
152
105
}
153
106
154
107
public async Task < LoginResultData > ContinueLogin ( LoginResultData loginResultData , string twofacode )
155
108
{
156
- var newAuth = loginResultData . NewAuth ;
109
+ var token = loginResultData . Token ;
157
110
var host = loginResultData . Host ;
158
111
var keychainAdapter = keychain . Connect ( host ) ;
159
112
var username = keychainAdapter . Credential . Username ;
160
113
var password = keychainAdapter . Credential . Token ;
161
114
try
162
115
{
163
116
logger . Trace ( "2FA Continue" ) ;
164
- var auth = await TryContinueLogin ( host , username , password , twofacode ) ;
165
-
166
- EnsureNonNullAuthorization ( auth ) ;
117
+ token = await TryContinueLogin ( host , username , password , twofacode ) ;
167
118
168
- keychain . SetToken ( host , auth . Token ) ;
119
+ if ( string . IsNullOrEmpty ( token ) )
120
+ {
121
+ throw new InvalidOperationException ( "Returned token is null or empty" ) ;
122
+ }
123
+
124
+ keychain . SetToken ( host , token ) ;
169
125
await keychain . Save ( host ) ;
170
126
171
127
return new LoginResultData ( LoginResultCodes . Success , "" , host ) ;
172
128
}
173
- catch ( TwoFactorAuthorizationException e )
174
- {
175
- logger . Trace ( e , "2FA TwoFactorAuthorizationException: {0} {1}" , LoginResultCodes . CodeFailed , e . Message ) ;
176
-
177
- return new LoginResultData ( LoginResultCodes . CodeFailed , Localization . Wrong2faCode , host , newAuth ) ;
178
- }
179
- catch ( ApiValidationException e )
180
- {
181
- logger . Trace ( e , "2FA ApiValidationException: {0}" , e . Message ) ;
182
-
183
- var message = e . ApiError . FirstErrorMessageSafe ( ) ;
184
- await keychain . Clear ( host , false ) ;
185
- return new LoginResultData ( LoginResultCodes . Failed , message , host ) ;
186
- }
187
129
catch ( Exception e )
188
130
{
189
131
logger . Trace ( e , "Exception: {0}" , e . Message ) ;
@@ -201,56 +143,12 @@ public async Task Logout(UriString hostAddress)
201
143
await new ActionTask ( keychain . Clear ( hostAddress , true ) ) . StartAwait ( ) ;
202
144
}
203
145
204
- private async Task < ApplicationAuthorization > CreateAndDeleteExistingApplicationAuthorization (
205
- IGitHubClient client ,
206
- NewAuthorization newAuth ,
207
- string twoFactorAuthenticationCode )
208
- {
209
- ApplicationAuthorization result ;
210
- var retry = 0 ;
211
-
212
- do
213
- {
214
- if ( twoFactorAuthenticationCode == null )
215
- {
216
-
217
- result = await client . Authorization . GetOrCreateApplicationAuthentication (
218
- clientId ,
219
- clientSecret ,
220
- newAuth ) ;
221
- }
222
- else
223
- {
224
- result = await client . Authorization . GetOrCreateApplicationAuthentication (
225
- clientId ,
226
- clientSecret ,
227
- newAuth ,
228
- twoFactorAuthenticationCode ) ;
229
- }
230
-
231
- if ( result . Token == string . Empty )
232
- {
233
- if ( twoFactorAuthenticationCode == null )
234
- {
235
- await client . Authorization . Delete ( result . Id ) ;
236
- }
237
- else
238
- {
239
- await client . Authorization . Delete ( result . Id , twoFactorAuthenticationCode ) ;
240
- }
241
- }
242
- } while ( result . Token == string . Empty && retry ++ == 0 ) ;
243
-
244
- return result ;
245
- }
246
-
247
- private async Task < ApplicationAuthorization > TryLogin (
146
+ private async Task < string > TryLogin (
248
147
UriString host ,
249
148
string username ,
250
149
string password
251
150
)
252
151
{
253
- ApplicationAuthorization auth ;
254
152
var loginTask = new OctorunTask ( taskManager . Token , nodeJsExecutablePath , octorunScript ,
255
153
"login" , ApplicationInfo . ClientId , ApplicationInfo . ClientSecret ) ;
256
154
loginTask . Configure ( processManager , workingDirectory : octorunScript . Parent . Parent , withInput : true ) ;
@@ -270,15 +168,14 @@ string password
270
168
271
169
if ( ret [ 0 ] == "success" )
272
170
{
273
- auth = new ApplicationAuthorization ( ret [ 1 ] ) ;
274
- return auth ;
171
+ return ret [ 1 ] ;
275
172
}
276
173
277
174
if ( ret [ 0 ] == "2fa" )
278
175
{
279
176
keychain . SetToken ( host , ret [ 1 ] ) ;
280
177
await keychain . Save ( host ) ;
281
- throw new TwoFactorRequiredException ( TwoFactorType . Unknown ) ;
178
+ throw new TwoFactorRequiredException ( ) ;
282
179
}
283
180
284
181
if ( ret . Count > 2 )
@@ -289,7 +186,7 @@ string password
289
186
throw new Exception ( "Authentication failed" ) ;
290
187
}
291
188
292
- private async Task < ApplicationAuthorization > TryContinueLogin (
189
+ private async Task < string > TryContinueLogin (
293
190
UriString host ,
294
191
string username ,
295
192
string password ,
@@ -298,7 +195,6 @@ string code
298
195
{
299
196
logger . Info ( "Continue Username:{0} {1} {2}" , username , password , code ) ;
300
197
301
- ApplicationAuthorization auth ;
302
198
var loginTask = new OctorunTask ( taskManager . Token , nodeJsExecutablePath , octorunScript ,
303
199
"login --twoFactor" , ApplicationInfo . ClientId , ApplicationInfo . ClientSecret ) ;
304
200
loginTask . Configure ( processManager , workingDirectory : octorunScript . Parent . Parent , withInput : true ) ;
@@ -321,8 +217,7 @@ string code
321
217
322
218
if ( ret [ 0 ] == "success" )
323
219
{
324
- auth = new ApplicationAuthorization ( ret [ 1 ] ) ;
325
- return auth ;
220
+ return ret [ 1 ] ;
326
221
}
327
222
328
223
if ( ret . Count > 2 )
@@ -332,47 +227,21 @@ string code
332
227
333
228
throw new Exception ( "Authentication failed" ) ;
334
229
}
335
-
336
- ApplicationAuthorization EnsureNonNullAuthorization ( ApplicationAuthorization auth )
337
- {
338
- // If a mock IGitHubClient is not set up correctly, it can return null from
339
- // IGitHubClient.Authorization.Create - this will cause an infinite loop in Login()
340
- // so prevent that.
341
- if ( auth == null )
342
- {
343
- throw new InvalidOperationException ( "IGitHubClient.Authorization.Create returned null." ) ;
344
- }
345
-
346
- return auth ;
347
- }
348
-
349
- bool EnterpriseWorkaround ( UriString hostAddress , Exception e )
350
- {
351
- // Older Enterprise hosts either don't have the API end-point to PUT an authorization, or they
352
- // return 422 because they haven't white-listed our client ID. In that case, we just ignore
353
- // the failure, using basic authentication (with username and password) instead of trying
354
- // to get an authorization token.
355
- var apiException = e as ApiException ;
356
- return ! HostAddress . IsGitHubDotCom ( hostAddress ) &&
357
- ( e is NotFoundException ||
358
- e is ForbiddenException ||
359
- apiException ? . StatusCode == ( HttpStatusCode ) 422 ) ;
360
- }
361
230
}
362
231
363
232
class LoginResultData
364
233
{
365
234
public LoginResultCodes Code ;
366
235
public string Message ;
367
- internal NewAuthorization NewAuth { get ; set ; }
236
+ internal string Token { get ; set ; }
368
237
internal UriString Host { get ; set ; }
369
238
370
239
internal LoginResultData ( LoginResultCodes code , string message ,
371
- UriString host , NewAuthorization newAuth )
240
+ UriString host , string token )
372
241
{
373
242
this . Code = code ;
374
243
this . Message = message ;
375
- this . NewAuth = newAuth ;
244
+ this . Token = token ;
376
245
this . Host = host ;
377
246
}
378
247
@@ -382,4 +251,8 @@ internal LoginResultData(LoginResultCodes code, string message, UriString host)
382
251
}
383
252
}
384
253
254
+ class TwoFactorRequiredException : Exception
255
+ {
256
+
257
+ }
385
258
}
0 commit comments