nodejs express + create-react-app oauth2.0 错误 401 'Invalid access token' Spotify API
nodejs express + create-react-app oauth2.0 error 401 'Invalid access token' Spotify API
我正在尝试构建一个允许我通过 nodejs express
服务器从 create-react-app
客户端调用 Spotify 的 API 的应用程序。我正在尝试使用 Authorization Code Flow.
它可以使用以下代码获取授权代码以生成 URL,完全在客户端(是否以及如何使用服务器端是另一个问题):
getSpotifyCodeUrl() {
const authEndPoint = 'https://accounts.spotify.com/authorize'
const clientId = CLIENT_ID;
const responseType = 'code';
const redirectUrl = 'http://localhost:3000/';
// TODO: state for cross-site request forgery protection
// cont state = '...';
const scope = 'user-read-private user-read-email';
return(
authEndPoint +
'?response_type=' + responseType +
'&client_id=' + clientId +
(scope ? '&scope=' + encodeURIComponent(scope) : '') +
'&redirect_uri=' + encodeURIComponent(redirectUrl)
)
}
用户只需单击带有上面生成的 href 的 link。
{!this.state.token ? <a className="btn btn--loginApp-link" href={this.getSpotifyCodeUrl()}>
Login to Spotify
</a> : ""}
用户重定向回来后,我使用以下函数从
中提取授权码
componentDidMount() {
this.setState({code: new URLSearchParams(window.location.search).get('code')});
}
使用代码我检索了访问令牌。客户来电:
getSpotifyAccessToken() {
fetch('/auth?code=' + this.state.code)
.then((res) => res.json())
.then(data => {
this.setState({token: data.token});
localStorage.setItem('token', this.state.token);
});
}
API 在服务器上调用:
app.get("/auth", (req, res) => {
let code = req.query.code;
let authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: 'http://localhost:3000/',
grant_type: 'authorization_code'
},
headers: {
'Authorization': 'Basic ' + (new Buffer.from(clientId + ':' + clientSecret).toString('base64'))
},
json: true
};
request.post(authOptions, function(error, response, body){
if (!error && response.statusCode === 200) {
token = body.access_token;
res.json({ token: "Token: " + body.access_token});
} else {
console.log("/auth response body")
console.log(body)
}
});
});
奇怪的是我得到了一个令牌,但在我的服务器终端中也可以看到以下错误:
{
error: 'invalid_grant',
error_description: 'Invalid authorization code'
}
如果我随后尝试使用该令牌执行来自客户端的(简单)请求:\
getSpotifyMe() {
fetch('/me?token=' + this.state.token)
.then((res) => res.json())
.then(data => {
console.log(data);
});
}
以及相应的服务器调用:
app.get("/me", (req, res) => {
let token = req.query.token;
console.log("Token: " + token);
let options = {
url: 'https://api.spotify.com/v1/me',
headers: { 'Authorization': 'Bearer ' + token },
json: true
}
request.get(options, function(error, response, body) {
console.log("/me request body");
console.log(body);
if (!error && response.statusCode === 200) {
res.json(body);
} else {
}
})
})
这给我一个 401 错误:
{ error: { status: 401, message: 'Invalid access token' } }
我已经尝试了一些东西。从客户那里打电话,没有成功。刷新令牌,删除 cookie,从帐户授权,但没有成功。奇怪的是我可以使用据说在 Spotify Web Console 中无效的令牌,执行与我在应用程序中尝试执行的完全相同的调用。
您知道我在应用程序中的什么地方导致了这些错误(invalid_grant 和 401)吗?我该如何解决它们?
我最终更密切地关注 the example on Spotify GitHub。
我将 create-react-app
更改为简单地调用 /login
服务器路由。不要像我尝试的那样使用 fetch,一旦服务器从不同的来源调用 Spotify API,你最终会遇到跨域错误。由于某些不明显的原因,我无法使用 href="/login"
,服务器根本没有响应,但这是另一个 SO 问题的结果。
<a href="http://localhost:3001/login">Login to Spotify</a>
服务器 index.js 现在只是授权代码流 app.js
,带有我自己的变量和一个小调整。
- 我的
redirect_uri
是 http://localhost:3001/callback
,我在 http://localhost:3000
重定向回我的客户 create-react-app
时费了好大劲儿,也许这就是问题所在授权码和访问令牌,IDK。您想直接进入 服务器端 回调。对用户来说也更加直观:点击一下,砰的一声,登录,中间没有乱七八糟的重定向。
- 在服务器上的
/callback
路由中,当 access_token
和 refresh_token
已成功检索或未成功检索时,这就是您要重定向回客户端的时候,http://localhost:3000
对我来说。当然有代币。该示例使用 URL 参数,我猜设置 cookie 也应该有效,但如果这是安全问题,则必须进行一些研究。
我对应用程序的 CORS 子句进行了小小的调整。除了来自我的客户端之外,服务器不需要传入请求,所以我在那里添加了一个 {origin: 'http://localhost:3000'}
以防万一。
app.use(express.static(__dirname + '../client/build'))
.use(cors({origin: 'http://localhost:3000'}))
.use(cookieParser());
就是这样,非常有效,我可以看到服务器端收到 /v1/me
调用的响应主体(示例代码中有一个控制台日志)并且令牌正在返回客户端.
我正在尝试构建一个允许我通过 nodejs express
服务器从 create-react-app
客户端调用 Spotify 的 API 的应用程序。我正在尝试使用 Authorization Code Flow.
它可以使用以下代码获取授权代码以生成 URL,完全在客户端(是否以及如何使用服务器端是另一个问题):
getSpotifyCodeUrl() {
const authEndPoint = 'https://accounts.spotify.com/authorize'
const clientId = CLIENT_ID;
const responseType = 'code';
const redirectUrl = 'http://localhost:3000/';
// TODO: state for cross-site request forgery protection
// cont state = '...';
const scope = 'user-read-private user-read-email';
return(
authEndPoint +
'?response_type=' + responseType +
'&client_id=' + clientId +
(scope ? '&scope=' + encodeURIComponent(scope) : '') +
'&redirect_uri=' + encodeURIComponent(redirectUrl)
)
}
用户只需单击带有上面生成的 href 的 link。
{!this.state.token ? <a className="btn btn--loginApp-link" href={this.getSpotifyCodeUrl()}>
Login to Spotify
</a> : ""}
用户重定向回来后,我使用以下函数从
中提取授权码componentDidMount() {
this.setState({code: new URLSearchParams(window.location.search).get('code')});
}
使用代码我检索了访问令牌。客户来电:
getSpotifyAccessToken() {
fetch('/auth?code=' + this.state.code)
.then((res) => res.json())
.then(data => {
this.setState({token: data.token});
localStorage.setItem('token', this.state.token);
});
}
API 在服务器上调用:
app.get("/auth", (req, res) => {
let code = req.query.code;
let authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: 'http://localhost:3000/',
grant_type: 'authorization_code'
},
headers: {
'Authorization': 'Basic ' + (new Buffer.from(clientId + ':' + clientSecret).toString('base64'))
},
json: true
};
request.post(authOptions, function(error, response, body){
if (!error && response.statusCode === 200) {
token = body.access_token;
res.json({ token: "Token: " + body.access_token});
} else {
console.log("/auth response body")
console.log(body)
}
});
});
奇怪的是我得到了一个令牌,但在我的服务器终端中也可以看到以下错误:
{ error: 'invalid_grant', error_description: 'Invalid authorization code' }
如果我随后尝试使用该令牌执行来自客户端的(简单)请求:\
getSpotifyMe() {
fetch('/me?token=' + this.state.token)
.then((res) => res.json())
.then(data => {
console.log(data);
});
}
以及相应的服务器调用:
app.get("/me", (req, res) => {
let token = req.query.token;
console.log("Token: " + token);
let options = {
url: 'https://api.spotify.com/v1/me',
headers: { 'Authorization': 'Bearer ' + token },
json: true
}
request.get(options, function(error, response, body) {
console.log("/me request body");
console.log(body);
if (!error && response.statusCode === 200) {
res.json(body);
} else {
}
})
})
这给我一个 401 错误:
{ error: { status: 401, message: 'Invalid access token' } }
我已经尝试了一些东西。从客户那里打电话,没有成功。刷新令牌,删除 cookie,从帐户授权,但没有成功。奇怪的是我可以使用据说在 Spotify Web Console 中无效的令牌,执行与我在应用程序中尝试执行的完全相同的调用。
您知道我在应用程序中的什么地方导致了这些错误(invalid_grant 和 401)吗?我该如何解决它们?
我最终更密切地关注 the example on Spotify GitHub。
我将 create-react-app
更改为简单地调用 /login
服务器路由。不要像我尝试的那样使用 fetch,一旦服务器从不同的来源调用 Spotify API,你最终会遇到跨域错误。由于某些不明显的原因,我无法使用 href="/login"
,服务器根本没有响应,但这是另一个 SO 问题的结果。
<a href="http://localhost:3001/login">Login to Spotify</a>
服务器 index.js 现在只是授权代码流 app.js
,带有我自己的变量和一个小调整。
- 我的
redirect_uri
是http://localhost:3001/callback
,我在http://localhost:3000
重定向回我的客户create-react-app
时费了好大劲儿,也许这就是问题所在授权码和访问令牌,IDK。您想直接进入 服务器端 回调。对用户来说也更加直观:点击一下,砰的一声,登录,中间没有乱七八糟的重定向。 - 在服务器上的
/callback
路由中,当access_token
和refresh_token
已成功检索或未成功检索时,这就是您要重定向回客户端的时候,http://localhost:3000
对我来说。当然有代币。该示例使用 URL 参数,我猜设置 cookie 也应该有效,但如果这是安全问题,则必须进行一些研究。
我对应用程序的 CORS 子句进行了小小的调整。除了来自我的客户端之外,服务器不需要传入请求,所以我在那里添加了一个 {origin: 'http://localhost:3000'}
以防万一。
app.use(express.static(__dirname + '../client/build'))
.use(cors({origin: 'http://localhost:3000'}))
.use(cookieParser());
就是这样,非常有效,我可以看到服务器端收到 /v1/me
调用的响应主体(示例代码中有一个控制台日志)并且令牌正在返回客户端.