Files
2026-04-07 17:41:25 +02:00

83 lines
2.7 KiB
Go

package auth
import (
"errors"
"fmt"
"protonvpn-wg-confgen/internal/constants"
)
// Error codes from ProtonVPN API
// Official source: github.com/ProtonMail/protoncore_android/.../ResponseCodes.kt
// See API_REFERENCE.md for full documentation.
const (
CodeSuccess = constants.APICodeSuccess
CodeWrongPassword = 8002 // PASSWORD_WRONG: Incorrect password
CodeWrongPasswordFormat = 8004 // Password format is incorrect (observed)
CodeCaptchaRequired = 9001 // HUMAN_VERIFICATION_REQUIRED: CAPTCHA needed
Code2FARequiredForVPN = 9100 // VPN-specific: certificate endpoint requires 2FA session (not in official docs)
CodeAccountDeleted = 10002 // ACCOUNT_DELETED: Account has been deleted
CodeAccountDisabled = 10003 // ACCOUNT_DISABLED: Account has been disabled
CodeMailboxPasswordError = 10013 // Legacy 2-password mode / invalid refresh token (context-dependent)
)
// Error represents an authentication error with ProtonVPN-specific error code
type Error struct {
Code int
Message string
}
// Error implements the error interface
func (e Error) Error() string {
return e.Message
}
// NewError creates a new authentication error from an API response code
func NewError(code int) error {
message := getErrorMessage(code)
return Error{
Code: code,
Message: message,
}
}
// getErrorMessage returns a human-readable error message for a given error code
func getErrorMessage(code int) string {
switch code {
case CodeWrongPassword:
return "incorrect username or password"
case CodeWrongPasswordFormat:
return "password format is incorrect"
case CodeCaptchaRequired:
return "CAPTCHA verification required"
case Code2FARequiredForVPN:
return "2FA required for VPN operations - your session was authenticated without 2FA (device trust). Use -clear-session to force re-authentication with 2FA"
case CodeAccountDeleted:
return "account has been deleted"
case CodeAccountDisabled:
return "account has been disabled"
case CodeMailboxPasswordError:
return "account uses legacy 2-password mode - please switch to single-password mode at account.proton.me"
default:
return fmt.Sprintf("authentication failed with code: %d", code)
}
}
// IsAccountError checks if the error is an account status error (deleted or disabled)
func IsAccountError(err error) bool {
var authErr Error
if !errors.As(err, &authErr) {
return false
}
return authErr.Code == CodeAccountDeleted || authErr.Code == CodeAccountDisabled
}
// IsCaptchaError checks if the error requires CAPTCHA verification
func IsCaptchaError(err error) bool {
var authErr Error
if !errors.As(err, &authErr) {
return false
}
return authErr.Code == CodeCaptchaRequired
}