Add 2FA in CLI

This commit is contained in:
Maidul Islam
2023-02-17 20:48:19 -05:00
parent 1d11f11eaf
commit be38844a5b
3 changed files with 114 additions and 0 deletions

View File

@@ -148,6 +148,28 @@ func CallLogin1V2(httpClient *resty.Client, request GetLoginOneV2Request) (GetLo
return loginOneV2Response, nil
}
func CallVerifyMfaToken(httpClient *resty.Client, request VerifyMfaTokenRequest) (*VerifyMfaTokenResponse, *VerifyMfaTokenErrorResponse, error) {
var verifyMfaTokenResponse VerifyMfaTokenResponse
var responseError VerifyMfaTokenErrorResponse
response, err := httpClient.
R().
SetResult(&verifyMfaTokenResponse).
SetHeader("User-Agent", USER_AGENT).
SetError(&responseError).
SetBody(request).
Post(fmt.Sprintf("%v/v2/auth/mfa/verify", config.INFISICAL_URL))
if err != nil {
return nil, nil, fmt.Errorf("CallVerifyMfaToken: Unable to complete api request [err=%s]", err)
}
if response.IsError() {
return nil, &responseError, nil
}
return &verifyMfaTokenResponse, nil, nil
}
func CallLogin2V2(httpClient *resty.Client, request GetLoginTwoV2Request) (GetLoginTwoV2Response, error) {
var loginTwoV2Response GetLoginTwoV2Response
response, err := httpClient.

View File

@@ -291,3 +291,35 @@ type GetLoginTwoV2Response struct {
ProtectedKeyIV string `json:"protectedKeyIV"`
ProtectedKeyTag string `json:"protectedKeyTag"`
}
type VerifyMfaTokenRequest struct {
Email string `json:"email"`
MFAToken string `json:"mfaToken"`
}
type VerifyMfaTokenResponse struct {
EncryptionVersion int `json:"encryptionVersion"`
Token string `json:"token"`
PublicKey string `json:"publicKey"`
EncryptedPrivateKey string `json:"encryptedPrivateKey"`
Iv string `json:"iv"`
Tag string `json:"tag"`
ProtectedKey string `json:"protectedKey"`
ProtectedKeyIV string `json:"protectedKeyIV"`
ProtectedKeyTag string `json:"protectedKeyTag"`
}
type VerifyMfaTokenErrorResponse struct {
Type string `json:"type"`
Message string `json:"message"`
Context struct {
Code string `json:"code"`
TriesLeft int `json:"triesLeft"`
} `json:"context"`
Level int `json:"level"`
LevelName string `json:"level_name"`
StatusCode int `json:"status_code"`
DatetimeIso time.Time `json:"datetime_iso"`
Application string `json:"application"`
Extra []interface{} `json:"extra"`
}

View File

@@ -70,6 +70,53 @@ var loginCmd = &cobra.Command{
return
}
if loginTwoResponse.MfaEnabled {
i := 1
for i < 6 {
mfaVerifyCode := askForMFACode()
httpClient := resty.New()
httpClient.SetAuthToken(loginTwoResponse.Token)
verifyMFAresponse, mfaErrorResponse, requestError := api.CallVerifyMfaToken(httpClient, api.VerifyMfaTokenRequest{
Email: email,
MFAToken: mfaVerifyCode,
})
if requestError != nil {
util.HandleError(err)
break
} else if mfaErrorResponse != nil {
if mfaErrorResponse.Context.Code == "mfa_invalid" {
msg := fmt.Sprintf("Incorrect, MFA code. You have %v attempts left", 5-i)
fmt.Println(msg)
if i == 5 {
util.PrintErrorMessageAndExit("No tries left, please try again in a bit")
break
}
}
if mfaErrorResponse.Context.Code == "mfa_expired" {
util.PrintErrorMessageAndExit("Your MFA code has expired, please try logging in again")
break
}
i++
} else {
loginTwoResponse.EncryptedPrivateKey = verifyMFAresponse.EncryptedPrivateKey
loginTwoResponse.EncryptionVersion = verifyMFAresponse.EncryptionVersion
loginTwoResponse.Iv = verifyMFAresponse.Iv
loginTwoResponse.ProtectedKey = verifyMFAresponse.ProtectedKey
loginTwoResponse.ProtectedKeyIV = verifyMFAresponse.ProtectedKeyIV
loginTwoResponse.ProtectedKeyTag = verifyMFAresponse.ProtectedKeyTag
loginTwoResponse.PublicKey = verifyMFAresponse.PublicKey
loginTwoResponse.Tag = verifyMFAresponse.Tag
loginTwoResponse.Token = verifyMFAresponse.Token
loginTwoResponse.EncryptionVersion = verifyMFAresponse.EncryptionVersion
break
}
}
}
var decryptedPrivateKey []byte
if loginTwoResponse.EncryptionVersion == 1 {
@@ -290,3 +337,16 @@ func generateFromPassword(password string, salt []byte, p *params) (hash []byte,
hash = argon2.IDKey([]byte(password), salt, p.iterations, p.memory, p.parallelism, p.keyLength)
return hash, nil
}
func askForMFACode() string {
mfaCodePromptUI := promptui.Prompt{
Label: "MFA verification code",
}
mfaVerifyCode, err := mfaCodePromptUI.Run()
if err != nil {
util.HandleError(err)
}
return mfaVerifyCode
}