dat*_*den 9 spotify reactjs auth0 axios refresh-token
背景
我正在我的 React 应用程序中测试隐式流身份验证,并尝试实现所谓的 静默刷新功能,在用户登录时,我定期要求一个新的访问令牌,而无需要求他提供新的授权。
以下是 Flow 模式Auth0 Tenant,在我的例子中,是 Spotify:
虽然使用隐式授权的 SPA(单页应用程序)不能使用刷新令牌,但还有其他方法可以提供类似的功能:
prompt=none调用/authorize端点时使用。用户不会看到登录或同意对话框。
/authorize从隐藏的 iframe调用并从父框架中提取新的访问令牌。用户不会看到重定向发生。
另一种方法是实现类似包axios-auth-refresh 的东西,一个库
帮助您通过
axios拦截器实现授权的自动刷新。当原始请求失败时,您可以轻松拦截原始请求,刷新授权并继续原始请求,无需任何用户交互。
用法:
import axios from 'axios';
import createAuthRefreshInterceptor from 'axios-auth-refresh';
// Function that will be called to refresh authorization
const refreshAuthLogic = failedRequest => axios.post('https://www.example.com/auth/token/refresh').then(tokenRefreshResponse => {
localStorage.setItem('token', tokenRefreshResponse.data.token);
failedRequest.response.config.headers['Authorization'] = 'Bearer ' + tokenRefreshResponse.data.token;
return Promise.resolve();
});
// Instantiate the interceptor (you can chain it as it returns the axios instance)
createAuthRefreshInterceptor(axios, refreshAuthLogic);
// Make a call. If it returns a 401 error, the refreshAuthLogic will be run,
// and the request retried with the new token
axios.get('https://www.example.com/restricted/area')
.then(/* ... */)
.catch(/* ... */);
Run Code Online (Sandbox Code Playgroud)
设置
这是我的Parent组件(请注意,isAuthenticated状态指的是我的应用程序身份验证,与Silent Refresh所需的 Spotify 令牌无关):
import SpotifyAuth from './components/spotify/Spotify';
class App extends Component {
constructor() {
super();
this.state = {
isAuthenticated: false,
isAuthenticatedWithSpotify: false,
spotifyToken: '',
tokenRenewed:''
};
this.logoutUser = this.logoutUser.bind(this);
this.loginUser = this.loginUser.bind(this);
this.onConnectWithSpotify = this.onConnectWithSpotify.bind(this);
};
UNSAFE_componentWillMount() {
if (window.localStorage.getItem('authToken')) {
this.setState({ isAuthenticated: true });
};
};
logoutUser() {
window.localStorage.clear();
this.setState({ isAuthenticated: false });
};
loginUser(token) {
window.localStorage.setItem('authToken', token);
this.setState({ isAuthenticated: true });
};
onConnectWithSpotify(token){
this.setState({ spotifyToken: token,
isAuthenticatedWithSpotify: true
}, () => {
console.log('Spotify Token', this.state.spotifyToken)
});
}
render() {
return (
<div>
<NavBar
title={this.state.title}
isAuthenticated={this.state.isAuthenticated}
/>
<section className="section">
<div className="container">
<div className="columns">
<div className="column is-half">
<br/>
<Switch>
<Route exact path='/' render={() => (
<SpotifyAuth
onConnectWithSpotify={this.onConnectWithSpotify}
spotifyToken={this.state.spotifyToken}
/>
)} />
<Route exact path='/login' render={() => (
<Form
formType={'Login'}
isAuthenticated={this.state.isAuthenticated}
loginUser={this.loginUser}
userId={this.state.id}
/>
)} />
<Route exact path='/logout' render={() => (
<Logout
logoutUser={this.logoutUser}
isAuthenticated={this.state.isAuthenticated}
spotifyToken={this.state.spotifyToken}
/>
)} />
</Switch>
</div>
</div>
</div>
</section>
</div>
)
}
};
export default App;
Run Code Online (Sandbox Code Playgroud)
以下是我的SpotifyAuth组件,当用户登录时,用户单击按钮以通过应用程序授权和验证他的 Spotify 帐户。
import Credentials from './spotify-auth.js'
import './Spotify.css'
class SpotifyAuth extends Component {
constructor (props) {
super(props);
this.state = {
isAuthenticatedWithSpotify: this.props.isAuthenticatedWithSpotify
};
this.state.handleRedirect = this.handleRedirect.bind(this);
};
generateRandomString(length) {
let text = '';
const possible =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
getHashParams() {
const hashParams = {};
const r = /([^&;=]+)=?([^&;]*)/g;
const q = window.location.hash.substring(1);
let e = r.exec(q);
while (e) {
hashParams[e[1]] = decodeURIComponent(e[2]);
e = r.exec(q);
}
return hashParams;
}
componentDidMount() {
//if (this.props.isAuthenticated) {
const params = this.getHashParams();
const access_token = params.access_token;
const state = params.state;
const storedState = localStorage.getItem(Credentials.stateKey);
localStorage.setItem('spotifyAuthToken', access_token);
localStorage.getItem('spotifyAuthToken');
if (window.localStorage.getItem('authToken')) {
this.setState({ isAuthenticatedWithSpotify: true });
};
if (access_token && (state == null || state !== storedState)) {
alert('Click "ok" to finish authentication with Spotify');
} else {
localStorage.removeItem(Credentials.stateKey);
}
this.props.onConnectWithSpotify(access_token);
};
handleRedirect(event) {
event.preventDefault()
const params = this.getHashParams();
const access_token = params.access_token;
console.log(access_token);
const state = this.generateRandomString(16);
localStorage.setItem(Credentials.stateKey, state);
let url = 'https://accounts.spotify.com/authorize';
url += '?response_type=token';
url += '&client_id=' + encodeURIComponent(Credentials.client_id);
url += '&scope=' + encodeURIComponent(Credentials.scope);
url += '&redirect_uri=' + encodeURIComponent(Credentials.redirect_uri);
url += '&state=' + encodeURIComponent(state);
window.location = url;
};
render() {
return (
<div className="button_container">
<h1 className="title is-4"><font color="#C86428">Welcome</font></h1>
<div className="Line" /><br/>
<button className="sp_button" onClick={(event) => this.handleRedirect(event)}>
<strong>LINK YOUR SPOTIFY ACCOUNT</strong>
</button>
</div>
)
}
}
export default SpotifyAuth;
Run Code Online (Sandbox Code Playgroud)
然而,Silent Refresh 不需要上面的按钮,也不需要渲染任何东西。
为完整起见,这是我用于我的应用程序身份验证过程的端点,它使用jwt-json Web 令牌来加密令牌并通过 cookie 从服务器到客户端将它们传递(但此加密工具未用于正在传递的 Spotify 令牌给我的客户,到目前为止):
@auth_blueprint.route('/auth/login', methods=['POST'])
def login_user():
# get post data
post_data = request.get_json()
response_object = {
'status': 'fail',
'message': 'Invalid payload.'
}
if not post_data:
return jsonify(response_object), 400
email = post_data.get('email')
password = post_data.get('password')
try:
user = User.query.filter_by(email=email).first()
if user and bcrypt.check_password_hash(user.password, password):
auth_token = user.encode_auth_token(user.id)
if auth_token:
response_object['status'] = 'success'
response_object['message'] = 'Successfully logged in.'
response_object['auth_token'] = auth_token.decode()
return jsonify(response_object), 200
else:
response_object['message'] = 'User does not exist.'
return jsonify(response_object), 404
except Exception:
response_object['message'] = 'Try again.'
return jsonify(response_object), 500
Run Code Online (Sandbox Code Playgroud)
题
考虑到上面的选项和代码,我如何使用我的设置来添加静默刷新并处理重定向到 Spotify 并在后台每小时获取一个新令牌?
介于此解决方案和我的代码之间的东西?
| 归档时间: |
|
| 查看次数: |
4933 次 |
| 最近记录: |