package oauth import ( "context" "crypto/rand" "fmt" "log" "net/http" "sync" "golang.org/x/oauth2" ) func GenerateToken( ctx *context.Context, oauth2Config *oauth2.Config, ) (*oauth2.Token, error) { verifier := oauth2.GenerateVerifier() state := rand.Text() var token *oauth2.Token wg := sync.WaitGroup{} var server http.Server server.Addr = "127.0.0.1" server.Handler = http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { code := r.URL.Query().Get("code") scope := r.URL.Query().Get("scope") resState := r.URL.Query().Get("state") if len(code) == 0 || len(scope) == 0 || resState != state { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } t, err := oauth2Config.Exchange(*ctx, code, oauth2.VerifierOption(verifier)) if err != nil { log.Fatalf("Could not exchange OAuth2 code: %v", err) http.Error( w, fmt.Sprintf("Could not exchange OAuth2 code: %v", err), http.StatusBadRequest, ) return } token = t http.Error( w, "Authentication successful! You may now close this tab.", http.StatusOK, ) if f, ok := w.(http.Flusher); ok { f.Flush() } wg.Done() server.Close() }, ) url := oauth2Config.AuthCodeURL( state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(verifier), ) log.Printf("Log in with Twitch: %s\n\n", url) wg.Add(1) if err := server.ListenAndServe(); err != http.ErrServerClosed { return nil, fmt.Errorf("http: %v", err) } wg.Wait() return token, nil }