Spotify Auth 访问令牌给出错误代码 400

问题描述 投票:0回答:1

我一直在尝试为我的 React Native 应用程序获取 Spotify 访问令牌和刷新令牌,但它给我带来了严重的问题。 https://docs.expo.dev/guides/authentication/#spotify 我能够使用 useAuthRequest 获取我的代码和状态。现在我尝试使用代码在客户端上获取我的应用程序的访问令牌和刷新令牌,但我不断遇到错误 400。因此,检查其他堆栈溢出问题时,我意识到在服务器上处理它会更好,因此我决定创建一个快速服务器来尝试获取访问代码

router.post('/get-spotify-access-code',(req: Request, res: Response)=>{
  console.log(req.body)
  const accessCode = req.body;
  var authOptions:AuthOptions = {
    url: 'https://accounts.spotify.com/api/token',
    form: {
      code: accessCode,
      redirect_uri: redirectUri,
      grant_type: 'authorization_code'
    },
    headers: {
      'content-type': 'application/x-www-form-urlencoded',
      'Authorization': 'Basic ' + Buffer.from(clientID + ':' + clientSecret).toString('base64')
    },
    json: true
  };
  request.post(authOptions, (error: any, response:any, body:any)=>{
    console.log(error);
    console.log(response)
    if(!error && response.statusCode === 200){
      const access_token = body.access_token;
      const refresh_token = body.refresh_token;
      const expires_in = body.expires_in;
      res.json({
          'access_token': access_token,
          'refresh_token': refresh_token,
          'expires_in': expires_in
      });
    }
  })      
})

但我仍然收到错误 400,而且我似乎无法弄清楚。请给我回复,我真的很感激。这是我在 React Native 应用程序上处理代码的方式

const [request2, response2, promptAsync2] = useAuthRequest({
        clientId: clientID,
        clientSecret: clientSecret,
        scopes: [
            'user-read-playback-state',
            'user-modify-playback-state',
            'user-read-currently-playing',
            'streaming',
            'playlist-read-private',
            'playlist-read-collaborative',
            'playlist-modify-private',
            'playlist-modify-public',
            'user-follow-modify',
            'user-follow-read',
            'user-read-playback-position',
            'user-library-modify',
            'user-library-read',
            'user-read-email',
            'user-read-private'
        ],
        usePKCE: false,
        redirectUri: makeRedirectUri({
            scheme: undefined
        })
    },
        discovery
    )
    useEffect(() => {
        if (response2?.type === 'success') {
            // get spotify access code
             const { code } = response2.params;
            const getSpotifyCode = async() =>{    
                const code2 = {
                    code
                }
                await axios.post('http://localhost:8005/get-spotify-access-code', code2).then(
                response =>{
                    console.log(response);
                }
               ).catch(error =>{
                console.log(error)
               })
            }
           getSpotifyCode()
        }
    }, [response2])

node.js typescript react-native backend spotify
1个回答
0
投票

您应该在运行 expo 和重定向 URL 端口之间匹配相同的端口。

我的重定向 URL 端口是 3000

https://developer.spotify.com/dashboard

Expo运行端口为3000

在package.json中

  "scripts": {
    "start": "expo start --port 3000",
    "android": "expo start --android --port 3000",
    "ios": "expo start --ios --port 3000",
    "web": "expo start --web --port 3000"
  },

演示代码

App.js

import * as React from 'react';
import * as WebBrowser from 'expo-web-browser';
import { makeRedirectUri, useAuthRequest } from 'expo-auth-session';
import { Button, View, Text, StyleSheet } from 'react-native';
import axios from 'axios';

WebBrowser.maybeCompleteAuthSession();

// Endpoint
const discovery = {
  authorizationEndpoint: 'https://accounts.spotify.com/authorize',
  tokenEndpoint: 'https://accounts.spotify.com/api/token'
};

const PORT = 3000; // Corrected: PORT should not be part of the config object
const CLIENT_ID = '<your client id>';
const CLIENT_SECRET = '<your client secret>';
const REDIRECT_URI = `http://localhost:${PORT}/callback`; // your redirect URI

export default function App() {
  const [request, response, promptAsync] = useAuthRequest(
    {
      clientId: CLIENT_ID,
      clientSecret: CLIENT_SECRET,
      scopes: ['user-read-email', 'playlist-modify-public'],
      usePKCE: false,
      redirectUri: REDIRECT_URI,
    },
    discovery
  );

  const [accessToken, setAccessToken] = React.useState("mockAccessToken");
  const [refreshToken, setRefreshToken] = React.useState("mockRefreshToken");

  React.useEffect(() => {
    if (response?.type === 'success') {
      const { code } = response.params;
      // Exchange code for access token and refresh token
      axios.post(
        'https://accounts.spotify.com/api/token',
        new URLSearchParams({
          'grant_type': 'authorization_code',
          'redirect_uri': REDIRECT_URI,
          'code': code
        }).toString(),
        {
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          auth: {
            username: CLIENT_ID,
            password: CLIENT_SECRET
          }
        }
      )
        .then((response) => {
          setAccessToken(response.data.access_token);
          setRefreshToken(response.data.refresh_token);
        })
        .catch((error) => {
          console.error('Error exchanging code for token:', error);
        });
    }
  }, [response]);


  return (
    <View style={styles.container}>
      <Button
        disabled={!request}
        title="Login"
        onPress={() => {
          promptAsync();
        }}
      />
      {accessToken && (
        <Text style={styles.tokenText}>Access Token: {accessToken}</Text>
      )}
      {refreshToken && (
        <Text style={styles.tokenText}>Refresh Token: {refreshToken}</Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
  },
  tokenText: {
    marginBottom: 20,
    fontSize: 16,
  },
});

package.json

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start --port 3000",
    "android": "expo start --android --port 3000",
    "ios": "expo start --ios --port 3000",
    "web": "expo start --web --port 3000"
  },
  "dependencies": {
    "@expo/metro-runtime": "~3.1.3",
    "@expo/vector-icons": "^14.0.0",
    "axios": "^1.6.8",
    "expo": "~50.0.14",
    "expo-auth-session": "~5.4.0",
    "expo-status-bar": "~1.11.1",
    "expo-web-browser": "~12.8.2",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-native": "0.73.6",
    "react-native-paper": "4.9.2",
    "react-native-web": "~0.19.6"
  }
}

安装依赖项

npm install

运行它

npm run web

结果

© www.soinside.com 2019 - 2024. All rights reserved.