2024-03-15 18:51:00 +00:00
|
|
|
package spotify
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/sha256"
|
2024-04-03 21:03:15 +00:00
|
|
|
"crypto/sha512"
|
|
|
|
"encoding/hex"
|
2024-03-15 18:51:00 +00:00
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2024-04-03 21:03:15 +00:00
|
|
|
"github.com/gofrs/uuid"
|
2024-03-15 18:51:00 +00:00
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"github.com/sirupsen/logrus"
|
2024-04-03 21:03:15 +00:00
|
|
|
"golang.org/x/crypto/pbkdf2"
|
2024-03-15 18:51:00 +00:00
|
|
|
"golang.org/x/oauth2"
|
|
|
|
)
|
|
|
|
|
2024-04-03 21:03:15 +00:00
|
|
|
const (
|
|
|
|
spotifyRequestTimeout = 2 * time.Second
|
|
|
|
|
|
|
|
pkcePBKDFIter = 210000
|
|
|
|
pkcePBKDFLen = 64
|
|
|
|
)
|
|
|
|
|
|
|
|
var instanceSalt = uuid.Must(uuid.NewV4()).String()
|
2024-03-15 18:51:00 +00:00
|
|
|
|
|
|
|
func handleStartAuth(w http.ResponseWriter, r *http.Request) {
|
|
|
|
channel := mux.Vars(r)["channel"]
|
2024-04-03 21:03:15 +00:00
|
|
|
pkceVerifier := hex.EncodeToString(pbkdf2.Key([]byte(channel), []byte(instanceSalt), pkcePBKDFIter, pkcePBKDFLen, sha512.New))
|
2024-03-15 18:51:00 +00:00
|
|
|
|
|
|
|
redirURL := baseURL.ResolveReference(&url.URL{Path: r.URL.Path})
|
|
|
|
conf, err := oauthConfig(channel, strings.Split(redirURL.String(), "?")[0])
|
|
|
|
if err != nil {
|
|
|
|
logrus.WithError(err).Error("getting Spotify oauth config")
|
|
|
|
http.Error(w, "unable to get Spotify config for this channel", http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
code := r.URL.Query().Get("code")
|
|
|
|
if code == "" {
|
|
|
|
http.Redirect(
|
|
|
|
w, r,
|
2024-04-03 21:03:15 +00:00
|
|
|
conf.AuthCodeURL(
|
|
|
|
fmt.Sprintf("%x", sha256.Sum256(append([]byte(conf.ClientID), []byte(channel)...))),
|
|
|
|
oauth2.S256ChallengeOption(pkceVerifier),
|
|
|
|
),
|
2024-03-15 18:51:00 +00:00
|
|
|
http.StatusFound,
|
|
|
|
)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-03 21:03:15 +00:00
|
|
|
token, err := conf.Exchange(
|
|
|
|
r.Context(),
|
|
|
|
r.URL.Query().Get("code"),
|
|
|
|
oauth2.VerifierOption(pkceVerifier),
|
|
|
|
)
|
2024-03-15 18:51:00 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.WithError(err).Error("getting Spotify oauth token")
|
|
|
|
http.Error(w, "unable to get Spotify auth token", http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = db.StoreEncryptedCoreMeta(strings.Join([]string{"spotify-auth", channel}, ":"), token); err != nil {
|
|
|
|
logrus.WithError(err).Error("storing Spotify oauth token")
|
|
|
|
http.Error(w, "unable to store Spotify auth token", http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-06-09 10:44:41 +00:00
|
|
|
http.Error(w, "Spotify is now authorized for this channel, you can close this page", http.StatusOK)
|
2024-03-15 18:51:00 +00:00
|
|
|
}
|