// TokenParser looks for a "token" GET parameter, decrypts and parses // it, and kills the request if anything fails along the way. func TokenParser(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { localContext := context.Get(r) token := r.URL.Query().Get("token") decryptedToken, err := crypto.Decrypt(token) if err != nil { panic(err) } err = json.Unmarshal([]byte(decryptedToken), &localContext.AuthTokens) if err != nil { panic(err) } if localContext.AuthTokens.AccessToken == "" { panic(errors.New("Missing access token")) } if localContext.AuthTokens.RefreshToken == "" { panic(errors.New("Missing refresh token")) } next.ServeHTTP(w, r) }) }
// Login handles login responses from the Spotify API func Login(globalContext *context.GlobalContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { csrfJSON, err := crypto.Decrypt(r.URL.Query().Get("state")) if err != nil { panic(err) } csrf := make(map[string]string) err = json.Unmarshal([]byte(csrfJSON), &csrf) if err != nil { panic(err) } if ip, ok := csrf["IP"]; !ok || ip != util.StripPort(r.RemoteAddr) { panic(errors.New("CSRF mismatch")) } if a, ok := csrf["User-Agent"]; !ok || a != r.Header.Get("User-Agent") { panic(errors.New("CSRF mismatch")) } data := map[string]interface{}{ "error": r.URL.Query().Get("error"), } if r.URL.Query().Get("error") == "" { redirectURI, err := loginURI(globalContext, r.Host) if err != nil { panic(err) } tokens, err := spotify.GetAuthTokens( globalContext.Spotify.ClientID, globalContext.Spotify.ClientSecret, r.URL.Query().Get("code"), redirectURI, ) data["expires_in"] = tokens.ExpiresIn jsonToken, err := json.Marshal(tokens) if err != nil { panic(err) } token, err := crypto.Encrypt(string(jsonToken)) if err != nil { panic(err) } data["token"] = token } err = globalContext.Templates.Login.Execute(w, data) if err != nil { panic(err) } } }