javascript - 在客户端 React 中存储 MSAL Graph API 令牌并重用它直到过期
问题描述
我对 React 还很陌生。这个问题与将身份验证令牌存储在客户端并重用它直到到期有关。
我正在使用 MSAL 在我的 React 应用程序中进行身份验证。下面是我的代码。
import * as React from 'react';
import {AuthOptions, CacheOptions, SystemOptions} from './MsalConfig';
import { UserAgentApplication } from 'msal';
//export const authContext: AuthenticationContext = new AuthenticationContext(msalConfig);
export const msalInstance = new UserAgentApplication({
auth: AuthOptions,
cache: CacheOptions,
system: SystemOptions
});
export const withAuth = function(WrappedComponent){
return class Auth extends React.Component{
constructor(props) {
super(props);
this.state = {
authenticated: false,
renewIframe: false,
hasError: false,
errorMessage: null,
graphAPIToken: null
};
}
componentWillMount() {
this.checkAuthentication();
}
checkAuthentication = () => {
if(this.state.graphAPIToken == null){
// action to perform on authentication
msalInstance.handleRedirectCallback(() => { // on success
this.setState({
authenticated: true
});
}, (authErr, accountState) => { // on fail
console.log("Error after graph API call " + authErr);
this.setState({
hasError: true,
errorMessage: authErr.errorMessage
});
});
// if we are inside renewal callback (hash contains access token), do nothing
if (msalInstance.isCallback(window.location.hash)) {
this.setState({
renewIframe: true
});
return;
}
// not logged in, perform full page redirect
if (!msalInstance.getAccount()) {
msalInstance.loginRedirect({});
return;
} else { // logged in, set authenticated state
this.setState({
authenticated: true
}, () => {
this.getAccessToken(msalInstance);
});
}
}
}
getAccessToken = (msalInstance) => {
console.log(msalInstance);
// if the user is already logged in you can acquire a token
if (msalInstance.getAccount()) {
var tokenRequest = {
scopes: ["user.read"]
};
msalInstance.acquireTokenSilent(tokenRequest)
.then(response => {
// get access token from response
// response.accessToken
console.log(response.accessToken);
this.setState({
graphAPIToken: response.accessToken
});
//return response.accessToken;
})
.catch(err => {
// could also check if err instance of InteractionRequiredAuthError if you can import the class.
if (err.name === "InteractionRequiredAuthError") {
return msalInstance.acquireTokenPopup(tokenRequest)
.then(response => {
// get access token from response
// response.accessToken
console.log(response.accessToken);
this.setState({
graphAPIToken: response.accessToken
});
//return response.accessToken;
})
.catch(err => {
console.log("Error inside getAccessToken " + err);
});
}
console.log("Error inside getAccessToken " + err);
});
} else {
// user is not logged in, you will need to log them in to acquire a token
console.log("u aren't logged in");
}
}
callGraphAPI = (token) => {
//..
}
render(){
if (this.state.renewIframe) {
return <div>hidden renew iframe - not visible</div>;
}
if (this.state.authenticated) {
return <WrappedComponent {...this.props} />;
}
if (this.state.hasError) {
console.log("Login error: " + this.state.errorMessage);
}
console.log("Login error: " + this.state.errorMessage);
}
};
}
现在,我在我的 React 路由中使用它index.js
:
ReactDOM.render(<MuiThemeProvider theme={theme}>
<Router>
<Switch>
<Route path="/" exact component={(withAuth)(Projects)}/>
<Route path="/signin" exact component={SignIn}/>
<Route path="/projects" exact component={(withAuth)(Projects)}/>
<Route path="/admin" exact component={(withAuth)(Admin)}/>
<Route path="/projectstages/:projectNumber" exact component={(withAuth)(ProjectStages)}/>
<Route path="/formspage" exact component={(withAuth)(FormsPage)}/>
<Route path="/users" exact component={(withAuth)(UserManagement)}/>
</Switch>
</Router>
</MuiThemeProvider>, document.getElementById('root'));
每当我访问任何 URL 时,都会调用componentWillMount
of组件来检查身份验证。withAuth
如何确保令牌只生成一次并存储在缓存中并重复使用直到过期?另外,我不确定我是否以正确的方式实施了身份验证。请问有什么帮助吗?
解决方案
您不必担心缓存令牌和更新它,MSAL 会为您完成这一切。
(事实上,如果您使用 MSAL,我特别建议您不要进行自己的令牌缓存。您可能会意外引入自己的安全漏洞。)
如文档中所述,每次您要发出 API 请求时,都应该调用acquireTokenSilent
. 将发生以下三种情况之一:
- 如果 MSAL 在其自己的缓存中具有与您提供的参数匹配的现有令牌,则 MSAL 将立即提供该令牌。
- 如果需要刷新令牌(例如,因为缓存的访问令牌已过期,或者因为您需要不同 API 的访问令牌),MSAL 将尝试执行静默令牌刷新。如果此操作以静默方式成功,MSAL 将提供新的访问令牌。
- 如果 MSAL 没有缓存的有效访问令牌,并且 MSAL 无法静默刷新它(例如,用户尚未登录、他们已注销或用户需要同意新权限),则 MSAL 将让您知道,您可以根据需要处理这种情况(例如
acquireTokenPopup
,使用弹出窗口或acquireTokenRedirect
使用重定向)。
推荐阅读
- elasticsearch - 如何使用 query_string 同时匹配嵌套和非嵌套字段?
- python - Torchtext 与 Pytorch v1.10?
- ms-access - MS Access mid 和 instr 函数
- c++ - 如何在没有 pow()、函数或递归的情况下在 c/c++ 中使用幂函数
- r - 尝试使用 rvest 提交表单时出现卷曲错误
- assembly - mac OS 中的一步一步的 hello world
- python - Discord cogs 无法加载
- regex - dicebear api 在尝试指定 skinColor 时返回 400 错误代码
- java - 它说 Process Finished 但没有输出
- database - 从角度获取数据库数据