授权和获取访问令牌后如何将用户传回前端客户端?

Posted

技术标签:

【中文标题】授权和获取访问令牌后如何将用户传回前端客户端?【英文标题】:How to pass user back to front end client after authorizing and obtaining access token? 【发布时间】:2020-12-10 04:01:40 【问题描述】:

我有一个 Django 后端和 React/Redux 前端,我正在尝试集成 Spotify API。我是一个完全的 django 菜鸟,所以请怜悯。我目前通过前端的常规 ol' 锚标签将用户发送到我的后端。然后我的后端将用户重定向到 Spotify 授权页面,然后该页面将他们重定向到另一个页面,该页面将授权代码换成我现在拥有的访问令牌。然而,这段代码和网址只是将我发送到我的后端 API。如何使用此访问令牌让用户回到前端? “我的”代码:

from django.views.generic.base import RedirectView, TemplateView
from rest_framework.response import Response
from rest_framework import generics, viewsets, permissions
from django.urls import reverse
from furl import furl
import requests


def build_authorize_url(request):
    params = 
        "client_id": "<client-id>",
        "response_type": "code",
        "redirect_uri": request.build_absolute_uri(
            reverse("spotify callback")
        ),
        "scope": " ".join(
            [
                'user-read-currently-playing',
                'user-modify-playback-state',
                'user-read-playback-state',
                'streaming',
                'app-remote-control',
                'playlist-read-collaborative',
                'playlist-modify-public',
                'playlist-read-private',
                'playlist-modify-private',
                'user-library-modify',
                'user-top-read',
                'user-read-playback-position',
                'user-read-recently-played',
            ]
        ),
    
    print(params)

    url = (
        furl("https://accounts.spotify.com/authorize")
        .add(params)
        .url
    )
    print(url)

    return url


AUTH_HEADER = 
    "Authorization": "Basic "
    + base64.b64encode(
        "<my client id>:<my client secret>".encode()
    ).decode()



def handle_callback(request):
    code = request.GET["code"]

    response = requests.post(
        "https://accounts.spotify.com/api/token",
        data=
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": request.build_absolute_uri(
                reverse("spotify callback")
            ),
        ,
        headers=AUTH_HEADER,
    )

    return response.json()


class SpotifyLoginView(RedirectView):
    query_string = True

    def get_redirect_url(self, *args, **kwargs):
        return build_authorize_url(self.request)


class SpotifyCallbackView(generics.GenericAPIView):
    def get(self, request, *args, **kwargs):
        print(handle_callback(request))

        return Response(handle_callback(request))

【问题讨论】:

【参考方案1】:

获取访问/刷新令牌后,您可以将用户重定向到您的前端 URL,并从 Spotify 的 Github 帐户(用 JS 编写,但想法相同)传递令牌值,例如 this official example:

res.redirect('/#' +
  querystring.stringify(
    access_token: access_token,
    refresh_token: refresh_token
  )
);

您可以阅读有关身份验证流程的更多信息here。

【讨论】:

但是在 url 中发送令牌不是吗?我想将它们作为 json 响应传递,然后将它们保存在本地存储中。 是的,它在 url 中发送令牌。但是在您的前端,您可以从 url 获取它们并将它们存储在本地存储中。 我会这样做,它看起来很老套。另外,我将如何处理刷新令牌?似乎我需要将用户发送回服务器以获得与原始身份验证代码类似的流程,而不是将其与刷新令牌一起使用。然而,在类似的现实世界情况下,用户不知道令牌正在被刷新。这是怎么发生的? @Morks 你可以在前端处理这个。如果您在响应中获得 401 状态,则您发送一个新请求并尝试刷新令牌。然后您使用新令牌再次发出请求。 根据 spotify API 站点,刷新流程与令牌流程相同,唯一的区别是刷新令牌用于代替授权码。也就是说,标头需要在令牌的 POST 请求中包含 clientId 和客户端密码,这就是需要从后端执行请求以不暴露客户端密码的原因。怎么可能在不暴露客户端机密的情况下从前端完成?

以上是关于授权和获取访问令牌后如何将用户传回前端客户端?的主要内容,如果未能解决你的问题,请参考以下文章

撤销 Keycloak 访问令牌

gdata OAuth2如何使用多个用户的令牌

从前端 JavaScript 代码获取 Spotify API 访问令牌

刷新谷歌访问令牌时未授权_客户端

如何存储访问令牌? (Oauth 2,Auth 代码流程)

3600秒后获取新的访问令牌