Spotify - 使用隐式流获取和更改用户数据

Posted

技术标签:

【中文标题】Spotify - 使用隐式流获取和更改用户数据【英文标题】:Spotify - get and change user data with Implicit Flow 【发布时间】:2020-05-13 09:04:53 【问题描述】:

我正在尝试为 Spotify api 实现一个简单的 python 客户端。根据Spotify's Authorization Guide,可以通过两种方式对app进行授权:

应用授权:Spotify 授权您的应用访问 Spotify 平台(API、SDK 和小部件)。 用户授权:Spotify 以及用户授予您的应用访问和/或修改用户自己的数据的权限。有关用户身份验证的信息,请参阅使用 OAuth 2.0 进行用户身份验证。对 Spotify Web API 的调用需要您的应用程序用户的授权。为了获得该授权,您的应用程序会生成对 Spotify Accounts Service /authorize 端点的调用,并传递寻求访问权限的范围列表。

客户凭证

我第一次尝试使用来自Spotipy 的oauth2 模块的应用授权,因为它不需要传递令牌,而只需要属于应用开发者的客户端ID 和客户端密码。

client.py

import spotipy
from spotipy.oauth2 import SpotifyClientCredentials

class SpotifyWrapper(spotipy.Spotify):
    def category_playlists(self, category, limit=50, offset=0):
        return self._get('browse/categories/%s/playlists' % category,
                         limit=limit,
                         offset=offset)

def get_api_client():
    # create a client authentication request
    client_cred = SpotifyClientCredentials(
        client_id=DevelopmentConfig.SPOTIFY_CLIENT_ID,
        client_secret=DevelopmentConfig.SPOTIFY_CLIENT_SECRET
    )

    # create a spotify client with a bearer token,
    # dynamically re-created if necessary
    return SpotifyWrapper(auth=client_cred.get_access_token())

那我就在这里导入并声明:

spotify_utilities.py

from app.resources.spotify.client import get_api_client

sp = get_api_client()

为了发出请求并获取用户播放列表,请像这样传递它:

def get_user_playlist(username, sp):
    ids=[]
    playlists = sp.user_playlists(username)
    for playlist in playlists['items']:
        ids.append(playlist['id'])
        print("Name: , Number of songs: , Playlist ID:  ".
              format(playlist['name'].encode('utf8'),
                     playlist['tracks']['total'],
                     playlist['id']))
    return ids

这可行并且会获取用户内容,用户是应用开发者


隐式流

现在我想转到隐式流,应用程序会询问任何使用访问权限和范围的用户,为此需要一个令牌。

一旦我使用 javascript 获取令牌,我就知道我可以使用它通过简单的请求获取用户数据访问 API:

GET_USER_PROFILE_ENDPOINT = 'https://api.spotify.com/v1/users/user_id'
GET_USER_PLAYLISTS_ENDPOINT = 'https://api.spotify.com/v1/users/user_id/playlists'

def get_user_profile(token, user_id):
    url = GET_USER_PROFILE_ENDPOINT.format(id=user_id)
    resp = requests.get(url, headers="Authorization": "Bearer ".format(token))
    print (len(resp.json()))
    return resp.json()

def get_user_playlists(token, user_id):
    url = GET_USER_PLAYLISTS_ENDPOINT..format(id=user_id)
    resp = requests.get(url, headers="Authorization": "Bearer ".format(token))
    print (len(resp.json()))
    return resp.json()

但为了首先获取(和更改)用户数据,我需要使用此令牌来获取 用户 ID


此外,通过以下示例表单 Spotipy 文档,用户必须在终端提供他的 用户名

if __name__ == '__main__':
    if len(sys.argv) > 1:
        username = sys.argv[1]
    else:
        print("Whoops, need your username!")
        print("usage: python user_playlists.py [username]")
        sys.exit()

    token = util.prompt_for_user_token(username)

    if token:
        sp = spotipy.Spotify(auth=token)
        playlists = sp.user_playlists(username)

在阅读了 Spotify 和 Spotify 的文档后,有些东西还不清楚:

    是否可以仅通过传递令牌来获取此 USER ID?

    应用用户是否必须通过浏览器中的表单提供其 Spotify 用户名此外在提示身份验证时授权应用?

    是否可以调整上面的包装器并实现一个考虑隐式流所需参数的客户端?只需 spotify = spotipy.Spotify(auth=token) 工作并获取当前的 usr 数据吗?

【问题讨论】:

【参考方案1】:

此外,通过以下示例表单 Spotipy 文档,用户必须提供 他在终端的用户名:

这是因为 Spotipy 将令牌缓存在磁盘上。当用户没有指定缓存路径时,用户名只会被附加到文件的文件扩展名中,如here 所示。因此,指定的用户名永远不会被传输到任何 Spotify API 端点。

1) 是否可以仅通过传递令牌来获取此 USER ID?

是的,使用 /v1/me 而不是 /v1/users/user_id 将完全做到这一点,前提是您使用的是授权代码流或隐式授予流生成的访问令牌。

2) 应用用户必须通过 浏览器中的表单,除了在身份验证时授权应用程序 提示?

不,正如我回答的第一段所见。

3) 是否可以调整上面的包装器并实现客户端 哪个考虑隐式流所需的参数?将 只需 spotify = spotipy.Spotify(auth=token) 工作并获取当前 usr 数据?

Spotipy 目前似乎只使用授权代码流。因为你说你是

尝试为 Spotify api 实现一个简单的 python 客户端。

您应该只在您的应用程序中实现隐式授予流程。 This 包含所有三个 Spotify 授权流程的示例。

【讨论】:

以上是关于Spotify - 使用隐式流获取和更改用户数据的主要内容,如果未能解决你的问题,请参考以下文章

我们真的需要在 OIDC 的隐式流中使用 id_token 吗?

OpenID 隐式流与标准流的示例用例是啥?

logoutid 在身份 server4 的隐式流中不可用

如何保护来自iframe的Oauth2隐式流

带有 React 的 Spotify 隐式授权流程 - 用户登录

Open ID Connect 和本机公共应用程序......没有隐式流,没有混合流......那又如何?