publish-vod/pkg/vault-oauth2/youtube/youtube.go

76 lines
2.3 KiB
Go
Raw Normal View History

// Package youtube uses the vaultoauth2 package to create a Youtube
// client and authorize it
package youtube
import (
"context"
"fmt"
"net/http"
"time"
vaultoauth2 "git.luzifer.io/luzifer/publish-vod/pkg/vault-oauth2"
"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/youtube/v3"
)
// GetOAuth2Client tries to get an oauth2.Config and oauth2.Token from
// the given Vault key. In case there is no token configured the code
// (which may be empty) is used to get the token from the Youtube API.
// In case no token and no code is available the retured error contains
// the required Auth-URL and should be printed to the user.
func GetOAuth2Client(ctx context.Context, vaultKey string) (client *http.Client, ts oauth2.TokenSource, err error) {
clientID, clientSecret, err := vaultoauth2.LoadClientDetailsFromVault(vaultKey)
if err != nil {
return nil, nil, fmt.Errorf("loading client details: %w", err)
}
c := &oauth2.Config{
ClientID: clientID,
ClientSecret: clientSecret,
Endpoint: google.Endpoint,
RedirectURL: "http://127.0.0.1:65285",
Scopes: []string{youtube.YoutubeUploadScope},
}
t, err := vaultoauth2.LoadTokenFromVault(vaultKey)
if err != nil {
codeChan := make(chan string, 1)
mux := http.NewServeMux()
mux.HandleFunc("/", func(_ http.ResponseWriter, r *http.Request) { codeChan <- r.URL.Query().Get("code") })
server := &http.Server{
Addr: ":65285",
Handler: mux,
ReadHeaderTimeout: time.Second,
}
go func() {
if err := server.ListenAndServe(); err != nil {
logrus.WithError(err).Fatal("creating listener for Youtube auth")
}
}()
logrus.Warnf("Youtube is not authorized, please do so by visiting %s", c.AuthCodeURL("offline", oauth2.AccessTypeOffline))
code := <-codeChan
if err = server.Shutdown(ctx); err != nil {
logrus.WithError(err).Error("shutting down auth-webserver")
}
// We got an auth-code to exchange for a token
t, err = c.Exchange(ctx, code)
if err != nil {
return nil, nil, fmt.Errorf("exchanging token: %w", err)
}
if err = vaultoauth2.SaveTokenToVault(vaultKey, t); err != nil {
return nil, nil, fmt.Errorf("storing initial token: %w", err)
}
}
ts = c.TokenSource(ctx, t)
return oauth2.NewClient(ctx, ts), ts, nil
}