@@ -49,6 +49,84 @@ func findSessionCookie(cookies []*http.Cookie) *http.Cookie {
49
49
return nil
50
50
}
51
51
52
+ func getLoginResponse (responseBody []byte ) (map [string ]interface {}, error ) {
53
+ var responseMap map [string ]interface {}
54
+ err := json .Unmarshal (responseBody , & responseMap )
55
+ if err != nil {
56
+ return nil , errors .New ("failed to parse login response: " + err .Error ())
57
+ }
58
+ loginRespRaw , ok := responseMap ["loginresponse" ]
59
+ if ! ok {
60
+ return nil , errors .New ("failed to parse login response, expected 'loginresponse' key not found" )
61
+ }
62
+ loginResponse , ok := loginRespRaw .(map [string ]interface {})
63
+ if ! ok {
64
+ return nil , errors .New ("failed to parse login response, expected 'loginresponse' to be a map" )
65
+ }
66
+ return loginResponse , nil
67
+ }
68
+
69
+ func getResponseBooleanValue (response map [string ]interface {}, key string ) (bool , bool ) {
70
+ v , found := response [key ]
71
+ if ! found {
72
+ return false , false
73
+ }
74
+ switch value := v .(type ) {
75
+ case bool :
76
+ return true , value
77
+ case string :
78
+ return true , strings .ToLower (value ) == "true"
79
+ case float64 :
80
+ return true , value != 0
81
+ default :
82
+ return true , false
83
+ }
84
+ }
85
+
86
+ func checkLogin2FAPromptAndValidate (r * Request , response map [string ]interface {}, sessionKey string ) error {
87
+ if ! r .Config .HasShell {
88
+ return nil
89
+ }
90
+ config .Debug ("Checking if 2FA is enabled and verified for the user " , response )
91
+ found , is2faEnabled := getResponseBooleanValue (response , "is2faenabled" )
92
+ if ! found || ! is2faEnabled {
93
+ config .Debug ("2FA is not enabled for the user, skipping 2FA validation" )
94
+ return nil
95
+ }
96
+ found , is2faVerified := getResponseBooleanValue (response , "is2faverified" )
97
+ if ! found || is2faVerified {
98
+ config .Debug ("2FA is already verified for the user, skipping 2FA validation" )
99
+ return nil
100
+ }
101
+ activeSpinners := r .Config .PauseActiveSpinners ()
102
+ fmt .Print ("Enter 2FA code: " )
103
+ var code string
104
+ fmt .Scanln (& code )
105
+ if activeSpinners > 0 {
106
+ r .Config .ResumePausedSpinners ()
107
+ }
108
+ params := make (url.Values )
109
+ params .Add ("command" , "validateUserTwoFactorAuthenticationCode" )
110
+ params .Add ("codefor2fa" , code )
111
+ params .Add ("sessionkey" , sessionKey )
112
+
113
+ msURL , _ := url .Parse (r .Config .ActiveProfile .URL )
114
+
115
+ config .Debug ("Validating 2FA with POST URL:" , msURL , params )
116
+ spinner := r .Config .StartSpinner ("trying to validate 2FA..." )
117
+ resp , err := r .Client ().PostForm (msURL .String (), params )
118
+ r .Config .StopSpinner (spinner )
119
+ if err != nil {
120
+ return errors .New ("failed to failed to validate 2FA code: " + err .Error ())
121
+ }
122
+ config .Debug ("ValidateUserTwoFactorAuthenticationCode POST response status code:" , resp .StatusCode )
123
+ if resp .StatusCode != http .StatusOK {
124
+ r .Client ().Jar , _ = cookiejar .New (nil )
125
+ return errors .New ("failed to validate 2FA code, please check the code. Invalidating session" )
126
+ }
127
+ return nil
128
+ }
129
+
52
130
// Login logs in a user based on provided request and returns http client and session key
53
131
func Login (r * Request ) (string , error ) {
54
132
params := make (url.Values )
@@ -81,6 +159,13 @@ func Login(r *Request) (string, error) {
81
159
return "" , e
82
160
}
83
161
162
+ body , _ := ioutil .ReadAll (resp .Body )
163
+ config .Debug ("Login response body:" , string (body ))
164
+ loginResponse , err := getLoginResponse (body )
165
+ if err != nil {
166
+ return "" , err
167
+ }
168
+
84
169
var sessionKey string
85
170
curTime := time .Now ()
86
171
expiryDuration := 15 * time .Minute
@@ -98,6 +183,9 @@ func Login(r *Request) (string, error) {
98
183
}()
99
184
100
185
config .Debug ("Login sessionkey:" , sessionKey )
186
+ if err := checkLogin2FAPromptAndValidate (r , loginResponse , sessionKey ); err != nil {
187
+ return "" , err
188
+ }
101
189
return sessionKey , nil
102
190
}
103
191
0 commit comments