[GH-ISSUE #100] Authentication example could be better #56

Closed
opened 2026-02-27 19:25:49 +03:00 by kerem · 15 comments
Owner

Originally created by @andersborgabiro on GitHub (Oct 6, 2017).
Original GitHub issue: https://github.com/jwilsson/spotify-web-api-php/issues/100

This library provides a great and broad abstraction of the Spotify Web API. Thank you for that.

The authentication example is not so good though, and doesn't work the way it's written.

This is how I did it. Note that everything is done in a single script, including all app state.

The try/catch should probably cover more than it does.

define('CLIENT_ID', 'xxxxxxxxxxxxxxxxxxxxxx');
define('CLIENT_SECRET', 'xxxxxxxxxxxxxxxxxxxxxxxx');
define('REDIRECT_URI', "http" . (!empty($_SERVER['HTTPS']) ? "s" : "") . "://" . $_SERVER['SERVER_NAME'] . $_SERVER['SCRIPT_NAME']);
define('SESSION', 'spotify_access_token');

...

$session = new SpotifyWebAPI\Session(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);

if (isset($_GET['code'])):
    $session->requestAccessToken($_GET['code']);
    $accessToken = $session->getAccessToken();
    $_SESSION[SESSION] = $accessToken;
    header('Location: index.php');
    die();
elseif (!isset($_SESSION[SESSION])):
    $options = ['scope' =>
        [
            'user-read-private',
            'user-read-email',
            'user-read-birthdate',
            'user-top-read',
            'playlist-read-private',
            'playlist-modify-private',
            'playlist-read-collaborative',
            'playlist-modify-public',
            'ugc-image-upload'
        ]
    ];
    header('Location: ' . $session->getAuthorizeUrl($options));
    die();
else:
    $accessToken = $_SESSION[SESSION];
endif;

try {
    $api = new SpotifyWebAPI\SpotifyWebAPI();
    $api->setAccessToken($accessToken);
    $api->setReturnType(SpotifyWebAPI\SpotifyWebAPI::RETURN_ASSOC);

    $me = $api->me();
    $userName = $me['display_name'];
    $userId = $me['id'];
    $userPicture = $me['images'][0]['url'];
}
catch (Exception $ex) {
    unset($_SESSION[SESSION]);
    header('Location: index.php');
    die();
}
Originally created by @andersborgabiro on GitHub (Oct 6, 2017). Original GitHub issue: https://github.com/jwilsson/spotify-web-api-php/issues/100 This library provides a great and broad abstraction of the Spotify Web API. Thank you for that. The authentication example is not so good though, and doesn't work the way it's written. This is how I did it. Note that everything is done in a single script, including all app state. The try/catch should probably cover more than it does. ``` define('CLIENT_ID', 'xxxxxxxxxxxxxxxxxxxxxx'); define('CLIENT_SECRET', 'xxxxxxxxxxxxxxxxxxxxxxxx'); define('REDIRECT_URI', "http" . (!empty($_SERVER['HTTPS']) ? "s" : "") . "://" . $_SERVER['SERVER_NAME'] . $_SERVER['SCRIPT_NAME']); define('SESSION', 'spotify_access_token'); ... $session = new SpotifyWebAPI\Session(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); if (isset($_GET['code'])): $session->requestAccessToken($_GET['code']); $accessToken = $session->getAccessToken(); $_SESSION[SESSION] = $accessToken; header('Location: index.php'); die(); elseif (!isset($_SESSION[SESSION])): $options = ['scope' => [ 'user-read-private', 'user-read-email', 'user-read-birthdate', 'user-top-read', 'playlist-read-private', 'playlist-modify-private', 'playlist-read-collaborative', 'playlist-modify-public', 'ugc-image-upload' ] ]; header('Location: ' . $session->getAuthorizeUrl($options)); die(); else: $accessToken = $_SESSION[SESSION]; endif; try { $api = new SpotifyWebAPI\SpotifyWebAPI(); $api->setAccessToken($accessToken); $api->setReturnType(SpotifyWebAPI\SpotifyWebAPI::RETURN_ASSOC); $me = $api->me(); $userName = $me['display_name']; $userId = $me['id']; $userPicture = $me['images'][0]['url']; } catch (Exception $ex) { unset($_SESSION[SESSION]); header('Location: index.php'); die(); } ```
kerem 2026-02-27 19:25:49 +03:00
  • closed this issue
  • added the
    docs
    label
Author
Owner

@jwilsson commented on GitHub (Oct 7, 2017):

Hi!
I'm a bit confused, which example are you referring to? The one in the README or the one in the Authorization Using the Authorization Code Flow article? And what seems to be the problem with the example you're referring to?

I'd be happy to improve the docs but I need something more concrete :)

<!-- gh-comment-id:334938396 --> @jwilsson commented on GitHub (Oct 7, 2017): Hi! I'm a bit confused, which example are you referring to? The one in the [README](https://github.com/jwilsson/spotify-web-api-php#usage) or the one in the [Authorization Using the Authorization Code Flow](https://github.com/jwilsson/spotify-web-api-php/blob/master/docs/examples/access-token-with-authorization-code-flow.md) article? And what seems to be the problem with the example you're referring to? I'd be happy to improve the docs but I need something more concrete :)
Author
Owner

@jwilsson commented on GitHub (Oct 7, 2017):

Sorry, I just remembered. There's a third example too, in the Getting Started article. Is it that one you're referring to?

<!-- gh-comment-id:334939050 --> @jwilsson commented on GitHub (Oct 7, 2017): Sorry, I just remembered. There's a third example too, in the [Getting Started](https://github.com/jwilsson/spotify-web-api-php/blob/master/docs/getting-started.md) article. Is it that one you're referring to?
Author
Owner

@andersborgabiro commented on GitHub (Oct 7, 2017):

I meant https://github.com/jwilsson/spotify-web-api-php/blob/master/docs/examples/access-token-with-authorization-code-flow.md

It's not wrong per se, rather not complete: It doesn't indicate how to retain state (initially I thought it did that within the SDK). I've further modified it to allow authentication after clicking a button (earlier the first thing the user had to do was to log in, which probably scared away users), but it's roughly the same:

Is Session() always needed?

$session = new SpotifyWebAPI\Session(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);

if (isset($_POST['logout'])):
    unset($_SESSION[SESSION]);
endif;

if (isset($_POST['login'])):
    $options = ['scope' =>
        [
            'user-read-private',
            'user-read-email',
            'user-read-birthdate',
            'user-top-read',
            'playlist-read-private',
            'playlist-modify-private',
            'playlist-read-collaborative',
            'playlist-modify-public',
            'ugc-image-upload'
        ]
    ];
    header('Location: ' . $session->getAuthorizeUrl($options));
    die();
endif;

if (isset($_GET['code'])):
    $session->requestAccessToken($_GET['code']);
    $_SESSION[SESSION] = $session->getAccessToken();
    header('Location: /');
    die();
endif;

$accessToken = isset($_SESSION[SESSION]) ? $_SESSION[SESSION] : false;

...

                    if ($accessToken !== false):
                        try {
                            $api = new SpotifyWebAPI\SpotifyWebAPI();
                            $api->setAccessToken($accessToken);
                            $api->setReturnType(SpotifyWebAPI\SpotifyWebAPI::RETURN_ASSOC);

                            $me = $api->me();
                            $userName = $me['display_name'];
                            $userId = $me['id'];
                            $userPicture = $me['images'][0]['url'];
                        }
                        catch (Exception $ex) {
                            unset($_SESSION[SESSION]);
                            header('Location: /');
                            die();
                        }

                        // Code for showing user info...
                    else:
                        print "<input class=\"btn btn-primary btn-lg\" type=\"submit\" name=\"login\" value=\"Login to Spotify\" />";
                    endif;

If you are interested, I can PM the link to the site.

<!-- gh-comment-id:334941513 --> @andersborgabiro commented on GitHub (Oct 7, 2017): I meant https://github.com/jwilsson/spotify-web-api-php/blob/master/docs/examples/access-token-with-authorization-code-flow.md It's not wrong per se, rather not complete: It doesn't indicate how to retain state (initially I thought it did that within the SDK). I've further modified it to allow authentication after clicking a button (earlier the first thing the user had to do was to log in, which probably scared away users), but it's roughly the same: Is Session() always needed? ``` $session = new SpotifyWebAPI\Session(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); if (isset($_POST['logout'])): unset($_SESSION[SESSION]); endif; if (isset($_POST['login'])): $options = ['scope' => [ 'user-read-private', 'user-read-email', 'user-read-birthdate', 'user-top-read', 'playlist-read-private', 'playlist-modify-private', 'playlist-read-collaborative', 'playlist-modify-public', 'ugc-image-upload' ] ]; header('Location: ' . $session->getAuthorizeUrl($options)); die(); endif; if (isset($_GET['code'])): $session->requestAccessToken($_GET['code']); $_SESSION[SESSION] = $session->getAccessToken(); header('Location: /'); die(); endif; $accessToken = isset($_SESSION[SESSION]) ? $_SESSION[SESSION] : false; ... if ($accessToken !== false): try { $api = new SpotifyWebAPI\SpotifyWebAPI(); $api->setAccessToken($accessToken); $api->setReturnType(SpotifyWebAPI\SpotifyWebAPI::RETURN_ASSOC); $me = $api->me(); $userName = $me['display_name']; $userId = $me['id']; $userPicture = $me['images'][0]['url']; } catch (Exception $ex) { unset($_SESSION[SESSION]); header('Location: /'); die(); } // Code for showing user info... else: print "<input class=\"btn btn-primary btn-lg\" type=\"submit\" name=\"login\" value=\"Login to Spotify\" />"; endif; ``` If you are interested, I can PM the link to the site.
Author
Owner

@jwilsson commented on GitHub (Oct 9, 2017):

Ah, you're right. I'll take a look at clarifying the token management in those examples.

The Session class is needed when first requesting a token, and every time you wish to refresh it.

<!-- gh-comment-id:335275315 --> @jwilsson commented on GitHub (Oct 9, 2017): Ah, you're right. I'll take a look at clarifying the token management in those examples. The `Session` class is needed when first requesting a token, and every time you wish to [refresh it](https://github.com/jwilsson/spotify-web-api-php/blob/master/docs/examples/access-token-with-authorization-code-flow.md#refreshing-an-access-token).
Author
Owner

@andersborgabiro commented on GitHub (Oct 9, 2017):

Then I can probably speed up the code a bit by skipping it normally. Sometimes the Spotiy API is slow/overloaded.

I currently don't do refresh, as users don't stay that long: making playlists based on artists' discographies.

<!-- gh-comment-id:335276776 --> @andersborgabiro commented on GitHub (Oct 9, 2017): Then I can probably speed up the code a bit by skipping it normally. Sometimes the Spotiy API is slow/overloaded. I currently don't do refresh, as users don't stay that long: making playlists based on artists' discographies.
Author
Owner

@jotasprout commented on GitHub (Oct 14, 2017):

First, of the three Spotify/PHP repos I've seen, this one is, by far, the easiest to read and understand. Your documentation is awesome and well organized. I'm also grateful this issue exists because the initial authorization part was all I really need so all of this discussion is way helpful. I stepped away from Spotify Web API for a few months and, when I got back, every little thing needed authorization and I was struggling to understand it. All my fun & easy projects screeched to a grinding halt. Or, are "screech" and "grind" mutually exclusive?

<!-- gh-comment-id:336652704 --> @jotasprout commented on GitHub (Oct 14, 2017): First, of the three Spotify/PHP repos I've seen, this one is, by far, the easiest to read and understand. Your documentation is awesome and well organized. I'm also grateful this issue exists because the initial authorization part was all I really need so all of this discussion is way helpful. I stepped away from Spotify Web API for a few months and, when I got back, every little thing needed authorization and I was struggling to understand it. All my fun & easy projects screeched to a grinding halt. Or, are "screech" and "grind" mutually exclusive?
Author
Owner

@jotasprout commented on GitHub (Oct 14, 2017):

Regarding the API, if nobody is using the app but me, am I correct in thinking all I need for authorizations are my public/private key? I just want to be able to make my requests again. I just want to access data on artists, albums, and tracks -- absolutely no user data.

I think that should still be simple but I can't figure it out. This is an "issue" with me not understanding (anymore) how to use the API, not with your code.

<!-- gh-comment-id:336653312 --> @jotasprout commented on GitHub (Oct 14, 2017): Regarding the API, if nobody is using the app but me, am I correct in thinking all I need for authorizations are my public/private key? I just want to be able to make my requests again. I just want to access data on artists, albums, and tracks -- absolutely no user data. I think that should still be simple but I can't figure it out. This is an "issue" with me not understanding (anymore) how to use the API, not with your code.
Author
Owner

@andersborgabiro commented on GitHub (Oct 14, 2017):

That worked before I required user logins in my app. Of course adding to a playlist (that I needed) didn't.

Yes, the library is great. It even converts arrays to comma-separated strings, which it took a while before I realized.

<!-- gh-comment-id:336662803 --> @andersborgabiro commented on GitHub (Oct 14, 2017): That worked before I required user logins in my app. Of course adding to a playlist (that I needed) didn't. Yes, the library is great. It even converts arrays to comma-separated strings, which it took a while before I realized.
Author
Owner

@jwilsson commented on GitHub (Oct 15, 2017):

Thanks for the kind words guys!

I just pushed an update to the authorization docs which I hope will clarify things. If not, just give me a shout or send a PR with your proposed changes :)

@jotasprout I'm guessing you've seen the Authorization Using the Client Credentials Flow article? That should contain everything you need to know. If you have any other questions, please open a new issue and I'll be happy to help out.

<!-- gh-comment-id:336692285 --> @jwilsson commented on GitHub (Oct 15, 2017): Thanks for the kind words guys! I just pushed [an update](https://github.com/jwilsson/spotify-web-api-php/commit/14bb6e6fbc8bc723af6a18a5e7af53fe9532237d) to the authorization docs which I hope will clarify things. If not, just give me a shout or send a PR with your proposed changes :) @jotasprout I'm guessing you've seen the [Authorization Using the Client Credentials Flow article](https://github.com/jwilsson/spotify-web-api-php/blob/master/docs/examples/access-token-with-client-credentials-flow.md)? That should contain everything you need to know. If you have any other questions, please open a new issue and I'll be happy to help out.
Author
Owner

@jotasprout commented on GitHub (Oct 16, 2017):

Nope. You guessed wrong. I totally thought "Authorization Flow" was what I needed and so I was trying to figure out which tiny piece(s) I needed. "Client Credentials" looks perfectly appropriate and I can't wait to try it later today.

<!-- gh-comment-id:336919874 --> @jotasprout commented on GitHub (Oct 16, 2017): Nope. You guessed wrong. I totally thought "Authorization Flow" was what I needed and so I was trying to figure out which tiny piece(s) I needed. "Client Credentials" looks perfectly appropriate and I can't wait to try it later today.
Author
Owner

@andersborgabiro commented on GitHub (Oct 16, 2017):

If there's no need for Spotify user login (depending on your use case), client credentials flow is the way to go. Don't forget to save the access token across page loads.

You don't need tiny pieces. You need the lot.

<!-- gh-comment-id:336922754 --> @andersborgabiro commented on GitHub (Oct 16, 2017): If there's no need for Spotify user login (depending on your use case), client credentials flow is the way to go. Don't forget to save the access token across page loads. You don't need tiny pieces. You need the lot.
Author
Owner

@jotasprout commented on GitHub (Oct 17, 2017):

It works! It works! It totally works!

<!-- gh-comment-id:337365417 --> @jotasprout commented on GitHub (Oct 17, 2017): It works! It works! It totally works!
Author
Owner

@andersborgabiro commented on GitHub (Oct 17, 2017):

Then try the authorization code flow (if you intend to affect user data). It's not much harder, except there are more states, and if you want to keep the token for long you need to use the refresh token. In my tests the access token seemed to always last an hour, and my app is fine with that, so I currently don't use the refresh token. The app does a "soft fall" when/if the token expires.

<!-- gh-comment-id:337408314 --> @andersborgabiro commented on GitHub (Oct 17, 2017): Then try the authorization code flow (if you intend to affect user data). It's not much harder, except there are more states, and if you want to keep the token for long you need to use the refresh token. In my tests the access token seemed to always last an hour, and my app is fine with that, so I currently don't use the refresh token. The app does a "soft fall" when/if the token expires.
Author
Owner

@jotasprout commented on GitHub (Oct 18, 2017):

Nope. I have no intention of affecting user data but thanks.

<!-- gh-comment-id:337590038 --> @jotasprout commented on GitHub (Oct 18, 2017): Nope. I have no intention of affecting user data but thanks.
Author
Owner

@jwilsson commented on GitHub (Oct 19, 2017):

I'm glad we got this figured out!

Since it looks like we're done here, I'm gonna close this issue. If you have any further questions or want it reopened, just let me know.

<!-- gh-comment-id:337985681 --> @jwilsson commented on GitHub (Oct 19, 2017): I'm glad we got this figured out! Since it looks like we're done here, I'm gonna close this issue. If you have any further questions or want it reopened, just let me know.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/spotify-web-api-php#56
No description provided.