Search code examples
phpoauth-2.0spotify

Spotify oauth2 with PHP curl. How to get authorization code?


I have tried following the spotify authorization code flow, and have fallen at the first hurdle of getting user authorization.

I have tried doing this using PHP curl.

If you take a look at my code, what am I doing wrong?

$url           = 'https://accounts.spotify.com/authorize';
$redirect_uri  = urlencode( site_url() );
$curl = curl_init();
 
curl_setopt( $curl, CURLOPT_URL, $url);
curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $curl, CURLOPT_HTTPGET, true );
curl_setopt( $curl, CURLOPT_POSTFIELDS, 'state=' );
curl_setopt( $curl, CURLOPT_POSTFIELDS, 'response_type=code' );
curl_setopt( $curl, CURLOPT_POSTFIELDS, 'scope=playlist-read-private%20playlist-modify-private' );
curl_setopt( $curl, CURLOPT_POSTFIELDS, 'client_id=' . $this->client_id );
curl_setopt( $curl, CURLOPT_POSTFIELDS, 'redirect_uri=' . $redirect_uri );
 
curl_exec( $curl );
curl_close( $curl );
 
$fullquery     = 'https://accounts.spotify.com/authorize?response_type=code&state=&client_id=CLIENT_ID&scope=playlist-read-private%20playlist-modify-private&redirect_uri=http%3A%2F%2Flocalhost%3A8888%2Fspotifyapi';

Running this returns a block of html from spotify, embedded into my page, with the text: "Error Oops! Something went wrong, please try again or check out our help area."

What's interesting however, is that if I put the full query into my search bar, it works exactly as I expect, by taking me to an authorization page, and after acceptance, redirecting back to my callback url, with my access code as a parameter in the url.

Why can't I get the desired effect in my PHP function?

Any hints would be greatly appreciated. I know there is a php spotify api wrapper on GitHub I could use, but I want to do this myself as a learning project.

spotify error response


Solution

  • You have to follow a 3 step process.

    I managed to get the first step which is outlined above to work by simply building the query out of the data above, and appending that to the authorization url - and adding a link on the page. Like this:

    $data = array(
        'client_id'     => $client_id,
        'redirect_uri'  => $redirect_url,
        'scope'         => $scope,
        'response_type' => $response_type,
    );
    
    $oauth_url = 'https://accounts.spotify.com/authorize?' . http_build_query( $data );
    ?>
    
    <a href="<?php echo $oauth_url; ?>">Login</a>
    

    Once the link is clicked, you are returned to the redirect url, where you can get the authorization code from the url, and continue with the authorization flow using curl.

    <?php if ( isset( $_GET['code'] ) && ! isset( $_SESSION['spotify_access'] ) ) {
    
        $data = array(
            'redirect_uri' => $redirect_url,
            'grant_type'   => 'authorization_code',
            'code'         => $_GET['code'],
        );
        $ch            = curl_init();
        curl_setopt( $ch, CURLOPT_URL, 'https://accounts.spotify.com/api/token' );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt( $ch, CURLOPT_POST, 1 );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $data ) );
        curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Authorization: Basic ' . base64_encode( $client_id . ':' . $client_secret ) ) );
    
        $result = json_decode( curl_exec( $ch ) );
    
    
        curl_close( $ch );
    
        if ( isset( $result->access_token ) ) {
            header( 'Location: http://localhost:8888/spotify/getprofile.php?access=' . $result->access_token );
        }
    }
    
    

    Finally, you can fetch user data:

    <?php if ( isset( $_GET['access'] ) ) {
        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, 'https://api.spotify.com/v1/me' );
        curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Content-Type:application/json', 'Authorization: Bearer ' . $_GET['access'] ) );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
        $userprofile = json_decode( curl_exec( $ch ) );
        curl_close( $ch );
    
        echo '<pre>';
        var_dump( $userprofile );
        echo '</pre>';
    
        if ( $userprofile->id ) {
            $ch = curl_init();
            curl_setopt( $ch, CURLOPT_URL, 'https://api.spotify.com/v1/users/' . $userprofile->id . '/playlists' );
            curl_setopt( $ch, CURLOPT_HTTPGET, 1 );
            curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
            curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Authorization: Bearer ' . $_GET['access'] ) );
            $playlists = json_decode( curl_exec( $ch ) );
            curl_close( $ch );
            echo '<pre>';
            var_dump( $playlists );
            echo '</pre>';
        }
    }