// From https://github.com/lukasaron/recaptcha // BLS-3 Licensed // Copyright (c) 2020, Lukas Aron // Modified by Kubuxu package main import ( "encoding/json" "io" "net/http" "net/url" "os" "time" ) // content type for communication with the verification server. const ( contentType = "application/json" ) // VerifyURL defines the endpoint which is called when a token needs to be verified. var ( VerifyURL, _ = url.Parse("https://www.google.com/recaptcha/api/siteverify") ) // Response defines the response format from the verification endpoint. type Response struct { Success bool `json:"success"` // status of the verification TimeStamp time.Time `json:"challenge_ts"` // timestamp of the challenge load (ISO format) HostName string `json:"hostname"` // the hostname of the site where the reCAPTCHA was solved Score float64 `json:"score"` // the score for this request (0.0 - 1.0) Action string `json:"action"` // the action name for this request ErrorCodes []string `json:"error-codes"` // error codes AndroidPackageName string `json:"apk_package_name"` // android related only } // VerifyToken function implements the basic logic of verification of ReCaptcha token that is usually created // on the user site (front-end) and then sent to verify on the server side (back-end). // To provide a successful verification process the secret key is required. Based on the security recommendations // the key has to be passed as an environmental variable SECRET_KEY. // // Token parameter is required, however remoteIP is optional. func VerifyToken(token, remoteIP string) (Response, error) { resp := Response{} if len(token) == 0 { resp.ErrorCodes = []string{"no-token"} return resp, nil } q := url.Values{} q.Add("secret", os.Getenv("RECAPTCHA_SECRET_KEY")) q.Add("response", token) q.Add("remoteip", remoteIP) var u *url.URL { verifyCopy := *VerifyURL u = &verifyCopy } u.RawQuery = q.Encode() r, err := http.Post(u.String(), contentType, nil) if err != nil { return resp, err } b, err := io.ReadAll(r.Body) _ = r.Body.Close() // close immediately after reading finished if err != nil { return resp, err } return resp, json.Unmarshal(b, &resp) }