diff --git a/pkg/provider/googleapps/example/challenge-selection.html b/pkg/provider/googleapps/example/challenge-selection.html
new file mode 100644
index 00000000..4919e873
--- /dev/null
+++ b/pkg/provider/googleapps/example/challenge-selection.html
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
+
+
+
+ Sign in - Google Accounts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2-Step Verification
+
To help keep your account safe, Google wants to make sure it’s really you trying to sign in
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pkg/provider/googleapps/googleapps.go b/pkg/provider/googleapps/googleapps.go
index 36a99f95..6ed44dae 100644
--- a/pkg/provider/googleapps/googleapps.go
+++ b/pkg/provider/googleapps/googleapps.go
@@ -448,6 +448,10 @@ func (kc *Client) loadChallengePage(submitURL string, referer string, authForm u
return kc.skipChallengePage(doc, submitURL, secondActionURL, loginDetails)
+ if extractNodeText(doc, "span", "Choose how you want to sign in:") != "" {
+ return kc.loadChallengeEntryPage(doc, submitURL, loginDetails)
+ }
+
} else if extractNodeText(doc, "h2", "To sign in to your Google Account, choose a task from the list below.") != "" {
return kc.loadChallengeEntryPage(doc, submitURL, loginDetails)
}
@@ -500,6 +504,40 @@ func (kc *Client) loadAlternateChallengePage(submitURL string, referer string, a
return kc.loadChallengeEntryPage(doc, submitURL, loginDetails)
}
+func (kc *Client) loadChallengePageSelection(doc *goquery.Document, submitURL string, loginDetails *creds.LoginDetails) (*goquery.Document, error) {
+ var challengeEntry string
+
+ doc.Find("div[data-challengeentry]").EachWithBreak(func(i int, s *goquery.Selection) bool {
+ action, ok := s.Attr("action")
+ if !ok {
+ return true
+ }
+
+ if strings.Contains(action, "challenge/totp/") ||
+ strings.Contains(action, "challenge/ipp/") ||
+ strings.Contains(action, "challenge/az/") ||
+ strings.Contains(action, "challenge/skotp/") {
+
+ challengeEntry, _ = s.Attr("data-challengeentry")
+ return false
+ }
+
+ return true
+ })
+
+ if challengeEntry == "" {
+ return nil, errors.New("unable to find supported second factor")
+ }
+
+ query := fmt.Sprintf(`[data-challengeentry="%s"]`, challengeEntry)
+ responseForm, newActionURL, err := extractInputsByFormQuery(doc, query)
+ if err != nil {
+ return nil, errors.Wrap(err, "unable to extract challenge form")
+ }
+
+ return kc.loadChallengePage(newActionURL, submitURL, responseForm, loginDetails)
+}
+
func (kc *Client) loadChallengeEntryPage(doc *goquery.Document, submitURL string, loginDetails *creds.LoginDetails) (*goquery.Document, error) {
var challengeEntry string