in pkg/provider/googleapps/googleapps.go [47:162]
func (kc *Client) Authenticate(loginDetails *creds.LoginDetails) (string, error) {
// Get the first page
authURL, authForm, err := kc.loadFirstPage(loginDetails)
if err != nil {
return "", errors.Wrap(err, "error loading first page")
}
authForm.Set("Email", loginDetails.Username)
passwordURL, passwordForm, err := kc.loadLoginPage(authURL+"?hl=en&loc=US", loginDetails.URL+"&hl=en&loc=US", authForm)
if err != nil {
return "", errors.Wrap(err, "error loading login page")
}
logger.Debugf("loginURL: %s", passwordURL)
authForm.Set("Passwd", loginDetails.Password)
referingURL := passwordURL
if _, rawIdPresent := passwordForm["rawidentifier"]; rawIdPresent {
authForm.Set("rawidentifier", loginDetails.Username)
referingURL = authURL
}
if v, tlPresent := passwordForm["TL"]; tlPresent {
authForm.Set("TL", v[0])
}
if v, gxfPresent := passwordForm["gxf"]; gxfPresent {
authForm.Set("gxf", v[0])
}
responseDoc, err := kc.loadChallengePage(passwordURL+"?hl=en&loc=US", referingURL, authForm, loginDetails)
if err != nil {
return "", errors.Wrap(err, "error loading challenge page")
}
captchaInputIds := []string{
"logincaptcha",
"identifier-captcha-input",
}
var captchaFound *goquery.Selection
var captchaInputId string
for _, v := range captchaInputIds {
captchaFound = responseDoc.Find(fmt.Sprintf("#%s", v))
if captchaFound != nil && captchaFound.Length() > 0 {
captchaInputId = v
break
}
}
for captchaFound != nil && captchaFound.Length() > 0 {
captchaImgDiv := responseDoc.Find(".captcha-img")
captchaPictureSrc, found := goquery.NewDocumentFromNode(captchaImgDiv.Children().Nodes[0]).Attr("src")
if !found {
return "", errors.New("captcha image not found but requested")
}
captchaPictureURL, err := generateFullURLIfRelative(captchaPictureSrc, passwordURL)
if err != nil {
return "", errors.Wrap(err, "error generating captcha image URL")
}
captcha, err := kc.tryDisplayCaptcha(captchaPictureURL)
if err != nil {
return "", err
}
captchaForm, captchaURL, err := extractInputsByFormID(responseDoc, "gaia_loginform", "challenge")
if err != nil {
return "", errors.Wrap(err, "error extracting captcha")
}
logger.Debugf("captchaURL: %s", captchaURL)
_, captchaV1 := captchaForm["Passwd"]
if captchaV1 {
captchaForm.Set("Passwd", loginDetails.Password)
}
captchaForm.Set(captchaInputId, captcha)
responseDoc, err = kc.loadChallengePage(captchaURL+"?hl=en&loc=US", captchaURL, captchaForm, loginDetails)
if err != nil {
return "", errors.Wrap(err, "error loading challenge page")
}
captchaFound = responseDoc.Find(fmt.Sprintf("#%s", captchaInputId))
}
// New Captcha proceeds back to password page
passworddBeingRequested := responseDoc.Find("#password")
if passworddBeingRequested != nil && passworddBeingRequested.Length() > 0 {
loginForm, loginURL, err := extractInputsByFormID(responseDoc, "challenge")
if err != nil {
return "", errors.Wrap(err, "error parsing password page after captcha")
}
loginForm.Set("Passwd", loginDetails.Password)
responseDoc, err = kc.loadChallengePage(loginURL+"?hl=en&loc=US", loginURL, loginForm, loginDetails)
if err != nil {
return "", errors.Wrap(err, "error loading challenge page")
}
}
samlAssertion := mustFindInputByName(responseDoc, "SAMLResponse")
if samlAssertion == "" {
return "", errors.New("page is missing saml assertion")
}
return samlAssertion, nil
}