Jammming Project, error: message: "Only valid bearer authentication supported" status: 400

Hi I’m trying to do this Jammming Project

https://www.codecademy.com/paths/full-stack-engineer-career-path/tracks/fscp-react-part-ii/modules/fecp-challenge-project-jammming/projects/jammming-prj

Literally have been staring at my screen for 3 days with no results I please need another pair of eyes to help me see what is wrong

When I try to search for a music artist i get this error and nothing is searching

  1. error:

  2. message: “Only valid bearer authentication supported”

  3. status: 400

here are my codes:

App.js

import React from 'react';
import './App.css';
import { SearchBar } from '../SearchBar/SearchBar.js';
import { SearchResults } from '../SearchResults/SearchResults.js';
import { Playlist } from '../Playlist/Playlist.js';
import Spotify from '../../util/Spotify.js'


export class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      searchResults: [],
      playlistName: 'My Playlist',
      playlistTracks: []
    };
    this.addTrack = this.addTrack.bind(this);
    this.removeTrack = this.removeTrack.bind(this);
    this.updatePlayListName = this.updatePlayListName.bind(this);
    this.savePlaylist = this.savePlaylist.bind(this);
    this.search = this.search.bind(this);
  }

  addTrack(track) {

    const tracks = this.state.playlistTracks;

    // tracks.find(saved => (saved.id !== track.id) && this.state.playlistTracks.push(track));

    // this.setState({ playlistTracks: tracks });
      
    /// my way has problems
    
    if (tracks.find(savedTrack => savedTrack.id === track.id)) {
      return; 
    }

    tracks.push(track);
    this.setState({ playlistTracks: tracks });

  }
  removeTrack(track) {
    let tracks = this.state.playlistTracks;
    
    tracks = tracks.filter(savedTrack => savedTrack.id !== track.id);
  
    this.setState({ playlistTracks: tracks });
  }

  updatePlayListName(name) {
    this.setState({ playlistName: name });
  }

  savePlaylist() {

    const trackUris = this.state.playlistTracks.map(track => track.uri);
    const name = this.state.playlistName;
    Spotify.savePlaylist(name, trackUris).then(() => {
      this.setState({
        playlistName: 'New Playlist',
        playlistTracks: []
      })
    })
  }

  search(term) {
    // console.log("appSearch " + term);
    // alert('searchbar clicked!')
    Spotify.search(term).then(searchResults => {
      this.setState({ searchResults: searchResults })
    });
    // console.log(this.state.searchResults.push("End of it"));
    // console.log(this.state.searchResults)
  }

  render() {
    return (
      <div>
        <h1>Ja<span className="highlight">mmm</span>ing</h1>
        <div className="App">
          <SearchBar onSearch={this.search} />
          <div className="App-playlist">
          <SearchResults 
            searchResults={this.state.searchResults}
            onAdd={this.addTrack} />
          <Playlist 
            playlistName={this.state.playlistName}
            playlistTracks={this.state.playlistTracks}
            onRemove={this.removeTrack}
            onNameChange={this.updatePlayListName}
            onSave={this.savePlaylist} />
        </div>
        </div>
      </div>
    )
  }
}

SearchBar.js

import React from 'react';
// import Spotify from '../../util/Spotify';
import './SearchBar.css';

export class SearchBar extends React.Component {
    constructor(props) {
        super(props);
        this.state = { 
            term: ""
        }
        this.search = this.search.bind(this);
        this.handleTermChange = this.handleTermChange.bind(this);
    }
    search() {
        // console.log(this.state.term);
        this.props.onSearch(this.state.term);
        // window.addEventListener('load', e => {
        //     e.preventDefault();
        //     Spotify.getAccessToken();
        // });
    }
    handleTermChange(event) {
        // console.log(event.target.value);
        this.setState({ term: event.target.value })
        // this.search(e.target.value);
    }
    render() {
        return (
            <div className="SearchBar">
                <input 
                    placeholder="Enter a song, album or an Artist"
                    onChange={this.handleTermChange} />
                <button onClick={this.search} className="SearchButton">Search</button>
            </div>
        )
    }
}

Playlist.js

import React from 'react';
import './Playlist.css';
import { TrackList } from '../TrackList/TrackList.js';


export class Playlist extends React.Component {
    constructor(props) {
        super(props);
        this.handleNameChange = this.handleNameChange.bind(this);
    }
    handleNameChange(e) {
        this.props.onNameChange(e.target.value);
    }
    render() {
        return (
            <div className="Playlist">
                <input 
                    defaultValue={'New Playlist'}
                    onChange={this.handleNameChange} />
                <TrackList 
                    tracks={this.props.playlistTracks}
                    onRemove={this.props.onRemove}
                    isRemoval={true} />
                <button 
                    className="Playlist-save"
                    onClick={this.props.onSave}>
                        SAVE TO SPOTIFY
                </button>
            </div>
        )
    }
}

SearchResults.js

import React from 'react';
import './SearchResults.css';
import { TrackList } from '../TrackList/TrackList.js';

export class SearchResults extends React.Component {
    render() {
        return (
            <div className="SearchResults">
                <h2>Results</h2>
                <TrackList 
                    tracks={this.props.searchResults}
                    onAdd={this.props.onAdd}
                    isRemoval={false} />
            </div>
        )
    }
}

TrackList.js

import React from 'react';
import './TrackList.css';
import { Track } from '../Track/Track.js';

export class TrackList extends React.Component {
    render() {
        return (
            <div className="TrackList">
                {
                    this.props.tracks &&
                    this.props.tracks.map(track => {
                        return <Track 
                            track={track}
                            key={track.id}
                            onAdd={this.props.onAdd}
                            onRemove={this.props.onRemove}
                            isRemoval={this.props.isRemoval} />
                    })
                }
            </div>
        )
    }
}

Track.js

import React from 'react';
import './Track.css';

export class Track extends React.Component {
    constructor(props) {
        super(props);
        this.addTrack = this.addTrack.bind(this);
        this.removeTrack = this.removeTrack.bind(this);
    }
    renderAction() {
        if (this.props.isRemoval) {
            return <button onClick={this.removeTrack} className="Track-action">-</button>
        } else {
            return <button onClick={this.addTrack} className="Track-action">+</button>
        }
    }
    addTrack() {
        this.props.onAdd(this.props.track);
    }
    removeTrack() {
        this.props.onRemove(this.props.track);
    }
    render() {
        return (
            <div className="Track">
                <div className="Track-information">
                    <h3>{this.props.track.name}</h3>
                    <p>{this.props.track.artist} | {this.props.track.album}</p>
                </div>
                {this.renderAction()}
            </div>
        )
    }
}

Spotify.js

const clientID = "API CODE COVERING IT UP BECAUSE OF POSTING HERE";
const redirectURI = "http://localhost:3000/";

let accessToken;


const Spotify = {
    getAccessToken() {
        if (accessToken) {
            return accessToken;
        }

        // check for access Token match 

        const accessTokenMatch = window.location.href.match(/access_token([^&]*)/);
        const expiresInMatch = window.location.href.match(/expires_in=([^&])*/);

        if (accessTokenMatch && expiresInMatch) {
            accessToken = accessTokenMatch[1];
            const expiresIn = Number(expiresInMatch[1]);
            // This clears the parameters, allowing us to grab a new access token when it expires.
            window.setTimeout(() => accessToken = "", expiresIn * 1000);
            window.history.pushState('Access Token', null, '/');
            return accessToken;
        } else {
            let accessURL = "https://accounts.spotify.com/authorize?client_id=" + clientID + "&response_type=token&scope=playlist-modify-public&redirect_uri=" + redirectURI;
         //                   "https://accounts.spotify.com/authorize?client_id=" + CLIENT_ID+ "&response_type=token&scope=playlist-modify-public&redirect_uri=" + REDIRECT_URI"
            window.location = accessURL;
        }
    },
    search(term) {
        let accessToken = Spotify.getAccessToken();
        let headers = {Authorization: `Bearer ${accessToken}`}
        // console.log(headers)
                
        return fetch(`https://api.spotify.com/v1/search?type=track&q=${term}`, {
            headers: { Authorization: headers }
        }).then(response => {
            // console.log("response search " + response);
            return response.json()
        }).then(jsonResponse => {
            console.log(jsonResponse);
            if (!jsonResponse.tracks) {
                return [];
            } else {
                return jsonResponse.tracks.items.map(track => ({
                    id: track.id,
                    name: track.name,
                    artist: track.artist[0].name,
                    album: track.album.name,
                    uri: track.uri
                }));
            };
        });
    },
    savePlaylist(name, trackUris) {
        if (!name || !trackUris.length) {
            return;
        }

        let accessToken = Spotify.getAccessToken();
        let headers = {Authorization: `Bearer ${accessToken}`}
        let userId;

        return fetch('https://api.spotify.com/v1/me', { 
            headers: headers 
        }).then(response => response.json()).then(jsonResponse => {
            console.log(jsonResponse);
            userId = jsonResponse.id;
            return fetch(`https://api.spotify.com/v1/users/${userId}/playlists`, {
                headers: headers,
                method: 'POST',
                body: JSON.stringify({ name: name })
            }).then(response => response.json()).then(jsonResponse => {
                console.log(jsonResponse);
                const playlistId = jsonResponse.id;
                return fetch(`https://api.spotify.com/v1/users/${userId}/playlists/${playlistId}/tracks`, {
                    headers: headers,
                    method: 'POST',
                    body: JSON.stringify({ uris: trackUris })
                })
            });
        });
    }
}



export default Spotify;

Hi @byte2358379181

^
This is redundant: You already defined your headers variable as an object, so you just need to paste it in like this: headers: headers.

I have done that now but the error is still persistent is the error in the getAccessToken()?
but getAccessToken() I have copied it word for word from the walk through video as well

If i log headers i have commented out i get

{Authorization: “Bearer =BQArhZ-_ddYOhFXqAMhzbhChRA6iQdnoabvwFGqIDY…lRH-l2mpOh_rfdak8aKCenXS8LH9rJUnlCekap4r40dFTNuVk”}

basically a token?

Spotify.js

const clientID = "API";
const redirectURI = "http://localhost:3000/";

let accessToken;


const Spotify = {
    getAccessToken() {
        if (accessToken) {
            return accessToken;
        }

        // check for access Token match 

        const accessTokenMatch = window.location.href.match(/access_token([^&]*)/);
        const expiresInMatch = window.location.href.match(/expires_in=([^&])*/);

        if (accessTokenMatch && expiresInMatch) {
            accessToken = accessTokenMatch[1];
            const expiresIn = Number(expiresInMatch[1]);
            // This clears the parameters, allowing us to grab a new access token when it expires.
            window.setTimeout(() => accessToken = "", expiresIn * 1000);
            window.history.pushState('Access Token', null, '/');
            return accessToken;
        } else {
            let accessURL = "https://accounts.spotify.com/authorize?client_id=" + clientID + "&response_type=token&scope=playlist-modify-public&redirect_uri=" + redirectURI;
         //                   "https://accounts.spotify.com/authorize?client_id=" + CLIENT_ID+ "&response_type=token&scope=playlist-modify-public&redirect_uri=" + REDIRECT_URI"
            window.location = accessURL;
        }
    },
    search(term) {
        const accessToken = Spotify.getAccessToken();
        const headers = {'Authorization': `Bearer ${accessToken}`}
        // console.log(headers)
                
        return fetch(`https://api.spotify.com/v1/search?type=track&q=${term}`, {
            headers: headers
        }).then(response => {
            // console.log("response search " + response);
            return response.json()
        }).then(jsonResponse => {
            console.log(jsonResponse);
            if (!jsonResponse.tracks) {
                return [];
            } else {
                return jsonResponse.tracks.items.map(track => ({
                    id: track.id,
                    name: track.name,
                    artist: track.artist[0].name,
                    album: track.album.name,
                    uri: track.uri
                }));
            };
        });
    },
    savePlaylist(name, trackUris) {
        if (!name || !trackUris.length) {
            return;
        }

        const accessToken = Spotify.getAccessToken();
        const headers = {Authorization: `Bearer ${accessToken}`}
        let userId;

        return fetch('https://api.spotify.com/v1/me', { 
            headers: headers 
        }).then(response => response.json()).then(jsonResponse => {
            console.log(jsonResponse);
            userId = jsonResponse.id;
            return fetch(`https://api.spotify.com/v1/users/${userId}/playlists`, {
                headers: headers,
                method: 'POST',
                body: JSON.stringify({ name: name })
            }).then(response => response.json()).then(jsonResponse => {
                console.log(jsonResponse);
                const playlistId = jsonResponse.id;
                return fetch(`https://api.spotify.com/v1/users/${userId}/playlists/${playlistId}/tracks`, {
                    headers: headers,
                    method: 'POST',
                    body: JSON.stringify({ uris: trackUris })
                })
            });
        });
    }
}



export default Spotify;

The access token shouldn’t start with an equal sign, I guess.

This RegEx doesn’t look right…

THANK YOU!! You are a legend now can I continue on with the project but where can I learn more about RegEx as it is alien language to me and the course Full-Stack so far hasn’t talk about it properly yet

1 Like

There is this brief course on Codecademy:
https://www.codecademy.com/learn/introduction-to-regular-expressions
and the MDN Docs about it:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

The basic information I missed at first is that you have to wrap a RegEx in slashes. Then you can evaluate it with .test() or .match(). The first returns a boolean, the second the value.

1 Like