func (d *DuoClient) ChallengeU2f(verificationHost string) (err error) {
	var sid, tx, txid, auth string
	var status = StatusResp{}
	tx = strings.Split(d.Signature, ":")[0]
	sid, err = d.DoAuth(tx, "", "")
	if err != nil {
		return
	}
	txid, err = d.DoPrompt(sid)
	if err != nil {
		return
	}
	auth, status, err = d.DoStatus(txid, sid)
	if err != nil {
		return
	}
	if status.Response.StatusCode == "u2f_sent" {
		var response *u2fhost.AuthenticateResponse
		allDevices := u2fhost.Devices()
		openDevices := []u2fhost.Device{}
		for i, device := range allDevices {
			err := device.Open()
			if err == nil {
				openDevices = append(openDevices, allDevices[i])
				defer func(i int) {
					allDevices[i].Close()
				}(i)
			}
		}
		if len(openDevices) == 0 {
			return errors.New("no open u2f devices")
		}
		var (
			err error
		)
		prompted := false
		timeout := time.After(time.Second * 25)
		interval := time.NewTicker(time.Millisecond * 250)
		facet := "https://" + verificationHost
		log.Debugf("Facet: %s", facet)
		var req = &u2fhost.AuthenticateRequest{
			Challenge: status.Response.U2FSignRequest[0].Challenge,
			AppId:     status.Response.U2FSignRequest[0].AppID,
			KeyHandle: status.Response.U2FSignRequest[0].KeyHandle,
			Facet:     facet,
		}
		defer interval.Stop()
		for {
			if response != nil {
				break
			}
			select {
			case <-timeout:
				fmt.Println("Failed to get registration response after 25 seconds")
				break
			case <-interval.C:
				for _, device := range openDevices {
					response, err = device.Authenticate(req)
					if err == nil {
						log.Printf("Authentication succeeded, continuing")
					} else if _, ok := err.(*u2fhost.TestOfUserPresenceRequiredError); ok {
						if !prompted {
							fmt.Fprintln(os.Stderr, "Touch the flashing U2F device to authenticate...")
							fmt.Fprintln(os.Stderr)
						}
						prompted = true
					} else {
						log.Printf("Got status response %#v\n", err)
						break
					}
				}
			}
		}
		txid, err = d.DoU2FPromptFinish(sid, status.Response.U2FSignRequest[0].SessionID, response)
		if err != nil {
			return fmt.Errorf("Failed on U2F_final. Err: %s", err)
		}
	}
	log.Printf("Device: %s", d.Device)
	if d.Device != "token" {
		auth, _, err = d.DoStatus(txid, sid)
		if err != nil {
			return
		}
	}
	err = d.DoCallback(auth)
	if err != nil {
		return
	}
	return
}
ChallengeU2F performs multiple call against an obscure Duo API.

Normally you use an iframe to perform those calls but here the main idea is
to fake Duo is order to use the CLI without any browser.

The function perform three successive calls to retry the challenge data.
Wait for the user to perform the verification (Duo Push or Yubikey). And then
call the callback url.

TODO: Use a Context to gracefully shutdown the thing and have a nice timeout
package lib
import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"os"
	"strings"
	"time"
	log "github.com/sirupsen/logrus"
	"net/url"
	u2fhost "github.com/marshallbrekka/go-u2fhost"
	uniformResourceLocator "net/url"
	"golang.org/x/net/html"
)
type DuoClient struct {
	Host       string
	Signature  string
	Callback   string
	Device     string
	StateToken string
	FactorID   string
}
type StatusResp struct {
	Response struct {
		SessionID      string `json:"sid"`
		U2FSignRequest []struct {
			Version   string `json:"version"`
			Challenge string `json:"challenge"`
			AppID     string `json:"appId"`
			KeyHandle string `json:"keyHandle"`
			SessionID string `json:"sessionId"`
		} `json:"u2f_sign_request"`
		Status     string `json:"status"`
		StatusCode string `json:"status_code"`
		Reason     string `json:"reason"`
		Parent     string `json:"parent"`
		Cookie     string `json:"cookie"`
		Result     string `json:"result"`
		ResultURL  string `json:"result_url"`
	} `json:"response"`
	Stat string `json:"stat"`
}
type PromptResp struct {
	Response struct {
		Txid string `json:"txid"`
	} `json:"response"`
	Stat string `json:"stat"`
}
func NewDuoClient(host, signature, callback, factorID string) *DuoClient {
	return &DuoClient{
		Host:      host,
		Signature: signature,
		Device:    "phone1",
		Callback:  callback,
		FactorID:  factorID,
	}
}
type FacetResponse struct {
	TrustedFacets []struct {
		Ids     []string `json:"ids"`
		Version struct {
			Major int `json:"major"`
			Minor int `json:"minor"`
		} `json:"version"`
	} `json:"trustedFacets"`
}
func (d *DuoClient) getTrustedFacet(appId string) (facetResponse *FacetResponse, err error) {
	client := &http.Client{}
	req, err := http.NewRequest("GET", appId, nil)
	if err != nil {
		return
	}
	res, err := client.Do(req)
	if err != nil {
		return
	}
	defer res.Body.Close()
	facetResponse = &FacetResponse{}
	err = json.NewDecoder(res.Body).Decode(facetResponse)
	if err != nil {
		return
	}
	return
}