You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+Supabase对接Spotify API遇401/403错误求助

Django + Supabase 实现Spotify OAuth登录后调用API报错问题排查与解决

问题背景

开发Django应用时,通过Supabase实现Spotify OAuth登录,调用Spotify API获取用户热门曲目时,先后遇到401、403错误,以及Uncaught (in promise) SyntaxError: Unexpected end of JSON input解析错误。相关代码如下:

认证视图代码

def spotify_auth(request):
    # Redirect the user to Supabase's OAuth authentication endpoint
    data = supabase_client.auth.sign_in_with_oauth({
                "provider": 'spotify',
                "scopes": 'user-top-read',
                "redirectTo": "http://127.0.0.1:8000//callback/",
                   
    })
    
    auth_url = data.url
    return redirect(auth_url)

前端存储token代码

// Get the fragment URL from the current URL
const fragmentUrl = window.location.hash;

// Parse the fragment URL to extract key-value pairs
const urlParams = new URLSearchParams(fragmentUrl.substring(1));

// Extract and save each piece of data
const access_token = urlParams.get('access_token');

// Save the extracted data to localStorage (or sessionStorage if needed)
localStorage.setItem('access_token', access_token);

前端调用Spotify API代码

<script>
const access_token = localStorage.getItem('access_token');
console.log("access token:",access_token)

const getTopTracks = async () => {
  const url = new URL('https://api.spotify.com/v1/me/top/tracks');
  url.searchParams.append('time_range', 'short-term');
  url.searchParams.append('limit', '20');

  const response = await fetch(url,{
    method:'GET',
    headers: { 'Authorization': 'Bearer ' + access_token },
  });

  const data = await response.json();
  console.log(data)
} 

getTopTracks();
</script>

核心错误点

你从URL hash中获取的access_token是Supabase自身的认证JWT令牌,并非Spotify官方API的访问令牌,直接用它调用Spotify API必然会触发权限错误。此外还有以下细节问题:

  • 回调地址存在双斜杠//,可能导致URL解析异常
  • 前端未处理API响应错误,非JSON响应直接解析会触发语法错误

解决步骤

1. 修正回调地址格式

将视图中的redirectTo从http://127.0.0.1:8000//callback/改为http://127.0.0.1:8000/callback/,确保URL格式正确,避免解析异常。

2. 后端获取Spotify官方访问令牌

不要在前端从hash提取token,而是在Django的callback视图中通过Supabase获取用户关联的Spotify provider令牌:

def spotify_callback(request):
    # 完成Supabase OAuth回调会话处理
    supabase_client.auth.get_session_from_url(request.build_absolute_uri())
    
    # 获取当前用户关联的Spotify provider令牌
    provider_token_data = supabase_client.auth.get_user_provider_access_token('spotify')
    spotify_access_token = provider_token_data['access_token']
    
    # 将令牌存入session,供后续请求使用
    request.session['spotify_access_token'] = spotify_access_token
    
    # 重定向到热门曲目页面
    return redirect('/top-tracks/')

3. 后端代理Spotify API请求(推荐方案)

直接在前端暴露Spotify令牌存在安全风险,建议通过后端代理API请求:

def top_tracks(request):
    spotify_access_token = request.session.get('spotify_access_token')
    if not spotify_access_token:
        return redirect('spotify_auth')
    
    # 调用Spotify API获取热门曲目
    import requests
    api_url = 'https://api.spotify.com/v1/me/top/tracks'
    params = {
        'time_range': 'short-term',
        'limit': 20
    }
    headers = {
        'Authorization': f'Bearer {spotify_access_token}'
    }
    
    response = requests.get(api_url, params=params, headers=headers)
    if response.status_code != 200:
        # 可添加令牌过期刷新逻辑
        return HttpResponse('获取热门曲目失败', status=response.status_code)
    
    tracks_data = response.json()
    return render(request, 'top_tracks.html', {'tracks': tracks_data})

4. 前端错误处理优化(若坚持前端调用)

如果必须前端调用API,需确保获取的是Spotify官方令牌,并添加错误处理:

<script>
const getTopTracks = async () => {
  // 从后端获取正确的Spotify令牌(可通过接口或模板变量传递)
  const spotify_access_token = localStorage.getItem('spotify_access_token');
  if (!spotify_access_token) {
    window.location.href = '/spotify-auth/';
    return;
  }

  const url = new URL('https://api.spotify.com/v1/me/top/tracks');
  url.searchParams.append('time_range', 'short-term');
  url.searchParams.append('limit', '20');

  try {
    const response = await fetch(url, {
      method: 'GET',
      headers: { 'Authorization': 'Bearer ' + spotify_access_token },
    });

    if (!response.ok) {
      console.error('API请求失败:', response.status, response.statusText);
      // 处理令牌过期等情况,比如跳转重新授权
      return;
    }

    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('请求出错:', error);
  }
}

getTopTracks();
</script>

5. 确认第三方配置正确性

  • 在Spotify开发者后台,确保回调地址与redirectTo完全一致(单斜杠)
  • 在Supabase控制台的Spotify OAuth配置中,确认已添加user-top-read权限范围
  • 检查Supabase的项目URL和API密钥配置是否正确

内容的提问来源于stack exchange,提问作者KevinL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 20:26:02