diff --git a/examples/interact/main.go b/examples/interact/main.go index f09e37f0d..2e5b049b4 100644 --- a/examples/interact/main.go +++ b/examples/interact/main.go @@ -135,6 +135,7 @@ func main() { }) globalInteraction.AddCustomInteraction(&interact.AuthInteract{ + Strict: true, Mode: interact.AuthModeToken, Token: "123", }) diff --git a/pkg/interact/auth.go b/pkg/interact/auth.go index dba8b0267..9d7ad19a8 100644 --- a/pkg/interact/auth.go +++ b/pkg/interact/auth.go @@ -2,9 +2,12 @@ package interact import ( "errors" + "os" + "time" "github.com/pquerna/otp" "github.com/pquerna/otp/totp" + log "github.com/sirupsen/logrus" ) type AuthMode string @@ -32,14 +35,39 @@ type AuthInteract struct { func (it *AuthInteract) Commands(interact *Interact) { if it.Strict { + // generate a one-time-use otp + if it.OneTimePasswordKey == nil { + opts := totp.GenerateOpts{ + Issuer: "interact", + AccountName: os.Getenv("USER"), + Period: 30, + } + log.Infof("[interact] one-time password key is not configured, generating one with %+v", opts) + key, err := totp.Generate(opts) + if err != nil { + panic(err) + } + + it.OneTimePasswordKey = key + } interact.Command("/auth", func(reply Reply) error { reply.Message("Enter your authentication token") return nil }).Next(func(token string, reply Reply) error { if token == it.Token { reply.Message("Token passed, please enter your one-time password") + + code, err := totp.GenerateCode(it.OneTimePasswordKey.Secret(), time.Now()) + if err != nil { + return err + } + + log.Infof("[interact] ======================================") + log.Infof("[interact] your one-time password code: %s", code) + log.Infof("[interact] ======================================") return nil } + return ErrAuthenticationFailed }).NamedNext(StateAuthenticated, func(code string, reply Reply, authorizer Authorizer) error { if totp.Validate(code, it.OneTimePasswordKey.Secret()) {