package google import ( "crypto/rand" "encoding/base64" . "ersteller-lib" "ersteller-lib/starter/ent" "ersteller-lib/starter/env" "net/http" "time" "golang.org/x/oauth2" "golang.org/x/oauth2/google" ) const oAuthStateCookieName = "oauthstate" const GoogleLogin = "/login/google" const GoogleLoginCallback = "/google/authenticated" type GoogleAuth struct { db *ent.Client server *http.ServeMux environment env.Environment config oauth2.Config } func NewGoogleAuth(db *ent.Client, server *http.ServeMux, environment env.Environment) *GoogleAuth { config := oauth2.Config{ ClientID: environment.GoogleClientId, ClientSecret: environment.GoogleClientSecret, Endpoint: google.Endpoint, RedirectURL: environment.BaseUrl + GoogleLoginCallback, Scopes: []string{}, } return &GoogleAuth{db: db, server: server, environment: environment, config: config} } func (g *GoogleAuth) AddRoutes() { g.server.HandleFunc("GET "+GoogleLogin, func(writer http.ResponseWriter, request *http.Request) { state := g.generateStateOauthCookie(writer) url := g.config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.ApprovalForce) http.Redirect(writer, request, url, http.StatusTemporaryRedirect) }) } func (g *GoogleAuth) generateStateOauthCookie(w http.ResponseWriter) string { b := make([]byte, 16) _, err := rand.Read(b) if err != nil { LogError("Failed to read random state: %v", err) } state := base64.URLEncoding.EncodeToString(b) var expiration = time.Now().Add(time.Hour) cookie := http.Cookie{Name: oAuthStateCookieName, Value: state, Expires: expiration, HttpOnly: true, Path: "/", Secure: false} if g.environment.IsLocal { cookie.SameSite = http.SameSiteLaxMode cookie.Secure = false } http.SetCookie(w, &cookie) return state }