Пример #1
0
// Ref: https://github.com/google/google-api-go-client/blob/master/examples/calendar.go
// Copyright 2014 The Go Authors. All rights reserved.
func tokenFromWeb(ctx context.Context, config *oauth2.Config) (*oauth2.Token, error) {
	ch := make(chan string)
	randState := fmt.Sprintf("st%d", time.Now().UnixNano())
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == "/favicon.ico" {
			w.WriteHeader(http.StatusNotFound)
			return
		}
		if r.FormValue("state") != randState {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		if code := r.FormValue("code"); code != "" {
			w.Write([]byte("<h1>Success</h1>Authorized."))
			w.(http.Flusher).Flush()
			ch <- code
			return
		}
		// no code
		w.WriteHeader(http.StatusInternalServerError)
	}))
	defer ts.Close()

	config.RedirectURL = ts.URL
	authURL := config.AuthCodeURL(randState)
	fmt.Println("Access to %s", authURL)
	code := <-ch

	return config.Exchange(ctx, code)
}
Пример #2
0
func ExecuteFlow(ctx context.Context, config *oauth2.Config, options ...Option) (*oauth2.Token, error) {
	o := processOpts(options)

	configCopy := *config
	config = &configCopy

	code := make(chan string)

	l, err := net.Listen("tcp", o.addr)
	if err != nil {
		return nil, err
	}
	defer l.Close()
	config.RedirectURL = fmt.Sprintf("http://%s/", l.Addr().String())

	go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, closeMessage)
		code <- r.FormValue("code") // send code to OAuth flow
	}))

	url := config.AuthCodeURL("", oauth2.AccessTypeOffline)
	if o.noBrowser {
		fmt.Fprintln(os.Stderr, visitMessage)
	} else if err := openURL(url); err != nil {
		fmt.Fprintln(os.Stderr, visitMessage)
	} else {
		fmt.Fprintln(os.Stderr, openedMessage)
	}
	fmt.Fprintf(os.Stderr, "\n%s\n\n", url)
	fmt.Fprintln(os.Stderr, resumeMessage)

	return config.Exchange(ctx, <-code)
}
Пример #3
0
func tokenFromWeb(ctx context.Context, config *oauth2.Config) *oauth2.Token {
	randState := fmt.Sprintf("st%d", time.Now().UnixNano())
	tokenOnce.Do(func() {
		http.HandleFunc("/oauth/", func(rw http.ResponseWriter, req *http.Request) {
			if req.FormValue("state") != randState {
				log.Printf("State doesn't match: req = %#v", req)
				http.Error(rw, "", 500)
				return
			}
			if code := req.FormValue("code"); code != "" {
				fmt.Fprintf(rw, "<h1>Success</h1>Authorized.")
				rw.(http.Flusher).Flush()
				ch <- code
				return
			}
			log.Printf("no code")
			http.Error(rw, "", 500)
		})
	})

	config.RedirectURL = "http://localhost:8383/oauth/"
	authURL := config.AuthCodeURL(randState)
	go openURL(authURL)
	log.Printf("Authorize this app at: %s", authURL)
	code := <-ch
	log.Printf("Got code: %s", code)

	token, err := config.Exchange(ctx, code)
	if err != nil {
		log.Fatalf("Token exchange error: %v", err)
	}
	return token
}
Пример #4
0
func tokenFromWeb(ctx context.Context, config *oauth2.Config, cfg *config.Config) *oauth2.Token {
	ch := make(chan string)
	randState := fmt.Sprintf("st%d", time.Now().UnixNano())

	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", cfg.GetYoutubeOAuthPort()))
	if err != nil {
		panic(err)
	}
	// make our own handler that puts all requests in a wait group.
	h := http.NewServeMux()

	// add a close handlefunc to that handler
	h.HandleFunc("/youtube_callback/", func(rw http.ResponseWriter, req *http.Request) {
		if req.URL.Path == "/favicon.ico" {
			http.Error(rw, "", 404)
			return
		}
		if req.FormValue("state") != randState {
			fmt.Printf("State doesn't match: req = %#v", req)
			http.Error(rw, "", 500)
			return
		}
		if code := req.FormValue("code"); code != "" {
			fmt.Fprintf(rw, "<h1>Success</h1>Authorized.")
			rw.(http.Flusher).Flush()
			ch <- code
			lis.Close()
			return
		}
		fmt.Printf("no code")
		http.Error(rw, "", 500)
		lis.Close()
	})

	//listen and serve until listner is closed
	go http.Serve(lis, h)

	// TODO fix this hard-coded localhost thingy
	config.RedirectURL = fmt.Sprintf("http://127.0.0.1:%d/youtube_callback/", cfg.GetYoutubeOAuthPort())
	authURL := config.AuthCodeURL(randState)
	go openURL(authURL)
	fmt.Printf("Authorize this app at: %s", authURL)
	code := <-ch

	token, err := config.Exchange(ctx, code)
	if err != nil {
		fmt.Printf("Token exchange error: %v", err)
	}
	return token
}
Пример #5
0
func tokenFromWeb(ctx context.Context, config *oauth2.Config, wf *web.WebFace) *oauth2.Token {
	ch := make(chan string)
	randState := fmt.Sprintf("st%d", time.Now().UnixNano())

	config.RedirectURL = "http://" + wf.Addr + "/login"

	{ // Auto
		authURL := config.AuthCodeURL(randState)

		wf.RedirectHandler = func(rw http.ResponseWriter, req *http.Request) {

			if req.URL.Path == "/favicon.ico" {
				http.Error(rw, "", 404)
				return
			}

			if !strings.HasPrefix(req.URL.Path, "/login") {
				log.Println("Redirect ", req.URL.Path, strings.HasPrefix(req.URL.Path, "/login"))
				http.Redirect(rw, req, authURL, 302)
				return
			}

			if req.FormValue("state") != randState {
				log.Printf("State doesn't match: req = %#v", req)
				http.Error(rw, "", 500)
				return
			}

			if code := req.FormValue("code"); code != "" {
				wf.RedirectHandler = nil
				http.Redirect(rw, req, "http://"+wf.Addr+"/", 302)
				ch <- code
				return
			}
		}

		log.Println("Awaiting Authorize Token")
	}

	code := <-ch
	log.Printf("Got code: %s", code)

	token, err := config.Exchange(ctx, code)
	if err != nil {
		log.Fatalf("Token exchange error: %v", err)
	}
	return token
}
Пример #6
0
func tokenFromWeb(ctx context.Context, config *oauth2.Config) {
	randState := fmt.Sprintf("st%d", time.Now().UnixNano())

	config.RedirectURL = "http://localhost:3000/after"

	http.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
		log.Printf("====> Got: %s", req.URL.Path)

		if req.URL.Path == "/favicon.ico" {
			http.Error(rw, "", 404)
			return
		}

		if req.URL.Path == "/" {
			authURL := config.AuthCodeURL(randState)
			http.Redirect(rw, req, authURL, http.StatusFound)
		}

		if req.FormValue("state") != randState {
			log.Printf("State doesn't match: %s / %s ", req.FormValue("state"), randState)
			http.Error(rw, "", 500)
			return
		}

		if code := req.FormValue("code"); code != "" {
			log.Printf("sending code")

			token, err := config.Exchange(ctx, code)

			if err == nil {
				// encode this thing
				var tokenBytes bytes.Buffer
				enc := gob.NewEncoder(&tokenBytes)
				enc.Encode(token)
				tokenString := base64.StdEncoding.EncodeToString(tokenBytes.Bytes())
				log.Printf(tokenString)
			}

			log.Printf("sent code")
			fmt.Fprintf(rw, "<h1>Success</h1>Authorized.")
			return
		}
		log.Printf("no code")
		http.Error(rw, "", 500)
	})

	http.ListenAndServe(":3000", nil)
}
Пример #7
0
func auth(cfg *oauth2.Config, fn func(string) error) (*oauth2.Token, error) {
	ch := make(chan interface{})

	l, err := net.Listen("tcp", ":0")
	if err != nil {
		return nil, err
	}
	defer l.Close()

	cfg.RedirectURL = urlFor(l.Addr())
	if err := fn(cfg.RedirectURL); err != nil {
		return nil, err
	}

	go func() {
		for {
			c, err := l.Accept()
			if err != nil {
				ch <- err
				return
			}

			code, err := serveConn(c, cfg)
			if err != nil {
				ch <- err
				return
			}

			if code == "" {
				continue
			}

			ch <- code
			return
		}
	}()

	v := <-ch
	switch t := v.(type) {
	case error:
		return nil, t
	case string:
		return cfg.Exchange(context.Background(), t)
	}

	panic("unreachable")
}
Пример #8
0
func GetAuthCodeURL(conf oauth2.Config, ar *osin.AuthorizeRequest, provider string) string {
	redirect, err := url.Parse(conf.RedirectURL)
	if err != nil {
		return ""
	}

	q := redirect.Query()
	q.Set(ProviderQueryParam, provider)
	q.Set(RedirectQueryParam, ar.RedirectUri)
	q.Set(ClientQueryParam, ar.Client.GetId())
	q.Set(ScopeQueryParam, ar.Scope)
	q.Set(StateQueryParam, ar.State)
	q.Set(TypeQueryParam, string(ar.Type))
	redirect.RawQuery = q.Encode()

	conf.RedirectURL = redirect.String()
	return conf.AuthCodeURL(ar.State)
}
Пример #9
0
// Get an authorization code by opening up the authorization page in a web
// browser.
func codeFromWeb(oauthConfig *oauth2.Config) (string, error) {
	ch := make(chan string)
	randState := fmt.Sprintf("st%d", time.Now().UnixNano())

	// Launch a local web server to receive the authorization code.
	ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		if req.URL.Path == "/favicon.ico" {
			http.Error(rw, "", 404)
			return
		}
		if req.FormValue("state") != randState {
			log.Printf("State doesn't match: req = %#v", req)
			http.Error(rw, "", 500)
			return
		}
		if code := req.FormValue("code"); code != "" {
			fmt.Fprintf(rw, "<h1>Success!</h1>Skicka is now authorized.")
			rw.(http.Flusher).Flush()
			ch <- code
			return
		}
		http.Error(rw, "", 500)
	}))
	defer ts.Close()

	oauthConfig.RedirectURL = ts.URL
	url := oauthConfig.AuthCodeURL(randState)

	errs := make(chan error)
	go func() {
		err := openURL(url)
		errs <- err
	}()

	err := <-errs
	if err == nil {
		// The URL open was apparently successful; wait for our server to
		// receive the code and send it back.
		code := <-ch
		return code, nil
	}
	return "", err
}
Пример #10
0
/**
 * This creates a new OAuth configuration and synchronizes concurrent access
 * to that configuration.
 * This is expected since ServerHTTP run on their own goroutine
 * @param path is the path to retrieve CA certificates
 * @param c is the channel to write to
 * @see #PopulateCertPool(string)
 */
func OAuthConfigurationManager(clientid, clientsecret, redirecturl, authurl, tokenurl string, c chan *oauth2.Config) {

	var logger = NewPrefixed("security#OAuthConfigurationManager")

	oauthConfig := new(oauth2.Config)
	oauthConfig.ClientID = clientid
	oauthConfig.ClientSecret = clientsecret
	oauthConfig.Scopes = []string{"email"}
	oauthConfig.RedirectURL = redirecturl
	oauthConfig.Endpoint = oauth2.Endpoint{
		AuthURL:  authurl,
		TokenURL: tokenurl,
	}

	for {
		select {
		case c <- oauthConfig:
			logger.Finest("Written OAuthconf : %v", oauthConfig)
		}
	}
}
Пример #11
0
func tokenFromWeb(ctx context.Context, config *oauth2.Config) *oauth2.Token {
	ch := make(chan string)
	randState := fmt.Sprintf("st%d", time.Now().UnixNano())
	ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		if req.URL.Path == "/favicon.ico" {
			http.Error(rw, "", 404)
			return
		}
		if req.FormValue("state") != randState {
			log.Printf("State doesn't match: req = %#v", req)
			http.Error(rw, "", 500)
			return
		}
		if code := req.FormValue("code"); code != "" {
			fmt.Fprintf(rw, "<h1>Success</h1>Authorized.")
			rw.(http.Flusher).Flush()
			ch <- code
			return
		}
		log.Printf("no code")
		http.Error(rw, "", 500)
	}))
	defer ts.Close()

	config.RedirectURL = ts.URL
	authURL := config.AuthCodeURL(randState)
	go openURL(authURL)
	log.Printf("Authorize this app at: %s", authURL)
	code := <-ch
	log.Printf("Got code: %s", code)

	token, err := config.Exchange(ctx, code)
	if err != nil {
		log.Fatalf("Token exchange error: %v", err)
	}
	return token
}
Пример #12
0
// Config does the initial creation of the token
//
// It may run an internal webserver to receive the results
func Config(name string, config *oauth2.Config) error {
	overrideCredentials(name, config)
	// See if already have a token
	tokenString := fs.ConfigFile.MustValue(name, "token")
	if tokenString != "" {
		fmt.Printf("Already have a token - refresh?\n")
		if !fs.Confirm() {
			return nil
		}
	}

	// Detect whether we should use internal web server
	useWebServer := false
	switch config.RedirectURL {
	case RedirectURL, RedirectPublicURL, RedirectLocalhostURL:
		useWebServer = true
	case TitleBarRedirectURL:
		fmt.Printf("Use auto config?\n")
		fmt.Printf(" * Say Y if not sure\n")
		fmt.Printf(" * Say N if you are working on a remote or headless machine or Y didn't work\n")
		useWebServer = fs.Confirm()
		if useWebServer {
			// copy the config and set to use the internal webserver
			configCopy := *config
			config = &configCopy
			config.RedirectURL = RedirectURL
		}
	}

	// Make random state
	stateBytes := make([]byte, 16)
	_, err := rand.Read(stateBytes)
	if err != nil {
		return err
	}
	state := fmt.Sprintf("%x", stateBytes)
	authURL := config.AuthCodeURL(state)

	// Prepare webserver
	server := authServer{
		state:       state,
		bindAddress: bindAddress,
		authURL:     authURL,
	}
	if useWebServer {
		server.code = make(chan string, 1)
		go server.Start()
		defer server.Stop()
		authURL = "http://" + bindAddress + "/auth"
	}

	// Generate a URL for the user to visit for authorization.
	_ = open.Start(authURL)
	fmt.Printf("If your browser doesn't open automatically go to the following link: %s\n", authURL)
	fmt.Printf("Log in and authorize rclone for access\n")

	var authCode string
	if useWebServer {
		// Read the code, and exchange it for a token.
		fmt.Printf("Waiting for code...\n")
		authCode = <-server.code
		if authCode != "" {
			fmt.Printf("Got code\n")
		} else {
			return fmt.Errorf("Failed to get code")
		}
	} else {
		// Read the code, and exchange it for a token.
		fmt.Printf("Enter verification code> ")
		authCode = fs.ReadLine()
	}
	token, err := config.Exchange(oauth2.NoContext, authCode)
	if err != nil {
		return fmt.Errorf("Failed to get token: %v", err)
	}
	return putToken(name, token)
}
Пример #13
0
// Config does the initial creation of the token
//
// It may run an internal webserver to receive the results
func Config(id, name string, config *oauth2.Config) error {
	changed := overrideCredentials(name, config)
	automatic := fs.ConfigFile.MustValue(name, fs.ConfigAutomatic) != ""

	// See if already have a token
	tokenString := fs.ConfigFile.MustValue(name, "token")
	if tokenString != "" {
		fmt.Printf("Already have a token - refresh?\n")
		if !fs.Confirm() {
			return nil
		}
	}

	// Detect whether we should use internal web server
	useWebServer := false
	switch config.RedirectURL {
	case RedirectURL, RedirectPublicURL, RedirectLocalhostURL:
		useWebServer = true
		if automatic {
			break
		}
		fmt.Printf("Use auto config?\n")
		fmt.Printf(" * Say Y if not sure\n")
		fmt.Printf(" * Say N if you are working on a remote or headless machine\n")
		auto := fs.Confirm()
		if !auto {
			fmt.Printf("For this to work, you will need rclone available on a machine that has a web browser available.\n")
			fmt.Printf("Execute the following on your machine:\n")
			if changed {
				fmt.Printf("\trclone authorize %q %q %q\n", id, config.ClientID, config.ClientSecret)
			} else {
				fmt.Printf("\trclone authorize %q\n", id)
			}
			fmt.Println("Then paste the result below:")
			code := ""
			for code == "" {
				fmt.Printf("result> ")
				code = strings.TrimSpace(fs.ReadLine())
			}
			token := &oauth2.Token{}
			err := json.Unmarshal([]byte(code), token)
			if err != nil {
				return err
			}
			return putToken(name, token)
		}
	case TitleBarRedirectURL:
		useWebServer = automatic
		if !automatic {
			fmt.Printf("Use auto config?\n")
			fmt.Printf(" * Say Y if not sure\n")
			fmt.Printf(" * Say N if you are working on a remote or headless machine or Y didn't work\n")
			useWebServer = fs.Confirm()
		}
		if useWebServer {
			// copy the config and set to use the internal webserver
			configCopy := *config
			config = &configCopy
			config.RedirectURL = RedirectURL
		}
	}

	// Make random state
	stateBytes := make([]byte, 16)
	_, err := rand.Read(stateBytes)
	if err != nil {
		return err
	}
	state := fmt.Sprintf("%x", stateBytes)
	authURL := config.AuthCodeURL(state)

	// Prepare webserver
	server := authServer{
		state:       state,
		bindAddress: bindAddress,
		authURL:     authURL,
	}
	if useWebServer {
		server.code = make(chan string, 1)
		go server.Start()
		defer server.Stop()
		authURL = "http://" + bindAddress + "/auth"
	}

	// Generate a URL for the user to visit for authorization.
	_ = open.Start(authURL)
	fmt.Printf("If your browser doesn't open automatically go to the following link: %s\n", authURL)
	fmt.Printf("Log in and authorize rclone for access\n")

	var authCode string
	if useWebServer {
		// Read the code, and exchange it for a token.
		fmt.Printf("Waiting for code...\n")
		authCode = <-server.code
		if authCode != "" {
			fmt.Printf("Got code\n")
		} else {
			return errors.New("failed to get code")
		}
	} else {
		// Read the code, and exchange it for a token.
		fmt.Printf("Enter verification code> ")
		authCode = fs.ReadLine()
	}
	token, err := config.Exchange(oauth2.NoContext, authCode)
	if err != nil {
		return errors.Wrap(err, "failed to get token")
	}

	// Print code if we do automatic retrieval
	if automatic {
		result, err := json.Marshal(token)
		if err != nil {
			return errors.Wrap(err, "failed to marshal token")
		}
		fmt.Printf("Paste the following into your remote machine --->\n%s\n<---End paste", result)
	}
	return putToken(name, token)
}