-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoauth.go
86 lines (71 loc) · 2.22 KB
/
oauth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package youtube
import (
"context"
"errors"
"net/http"
"net/url"
"sync"
"github.com/rs/zerolog/log"
"github.com/pkg/browser"
"golang.org/x/oauth2"
"google.golang.org/api/youtube/v3"
"mkuznets.com/go/ytbackup/pkg/obscure"
)
const (
clientID = "1tpWYwsqI8HKDXHnE3wiuthJU8AXQJx1Rx3sW0LHd0OFC-fjYmAPU3-oWgbt9tXpm1SE8hn2zV0EifEx0D-FsuLTmDgti3v_D74r_E-gd3Xs5GZLkA0ahQ" // nolint
clientSecret = "xgLU2qax3MjRda0GDo_rzoAVdED4kRp4XYLENwR7El7JZDVPpUuy0Q" // nolint
)
func NewConfig() *oauth2.Config {
return &oauth2.Config{
ClientID: obscure.MustReveal(clientID),
ClientSecret: obscure.MustReveal(clientSecret),
RedirectURL: "http://127.0.0.1:7798",
Scopes: []string{youtube.YoutubeReadonlyScope},
Endpoint: oauth2.Endpoint{
AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://oauth2.googleapis.com/token",
},
}
}
func NewToken(ctx context.Context, config *oauth2.Config) (*oauth2.Token, error) {
redirectURL, err := url.Parse(config.RedirectURL)
if err != nil {
return nil, err
}
codeCh := make(chan string)
srv := &http.Server{Addr: ":" + redirectURL.Port()}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
codeCh <- r.FormValue("code")
w.Header().Set("Content-Type", "text/plain")
// noinspection GoUnhandledErrorResult
w.Write([]byte("You can now safely close this browser window.")) // nolint
})
wg := &sync.WaitGroup{}
defer wg.Wait()
wg.Add(1)
go func() {
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Err(err).Msg("ListenAndServe()")
}
wg.Done()
}()
defer func() {
go stopServer(ctx, srv)
}()
// TODO: support manual code entry for remote setups
// https://developers.google.com/identity/protocols/oauth2/native-app#manual-copypaste
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
go openURL(authURL)
code := <-codeCh
return config.Exchange(ctx, code)
}
func openURL(u string) {
if err := browser.OpenURL(u); err != nil {
log.Err(err).Msg("browser.OpenURL")
}
}
func stopServer(ctx context.Context, srv *http.Server) {
if e := srv.Shutdown(ctx); e != nil {
log.Err(e).Msg("Server shutdown")
}
}