在客户端 React 中存储 MSAL Graph API 令牌并重复使用它直到过期
Storing MSAL Graph API token in client side React and reusing it until expiry
我是 React 的新手。这个问题是关于在客户端存储身份验证令牌并重复使用它直到到期。
我在我的 React 应用程序中使用 MSAL 进行身份验证。下面是我的代码。
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);
}
};
}
现在,我在 index.js
的 React 路由中使用它:
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 时,withAuth
组件的 componentWillMount
将被调用以检查身份验证。如何确保令牌只生成一次并存储在缓存中并重复使用直到过期?另外,我不确定我是否以正确的方式实施了身份验证。请问有什么帮助吗?
您不必担心令牌的缓存和更新,MSAL 会为您完成这一切。
(事实上,如果您使用的是 MSAL,我特别建议您不要 进行自己的令牌缓存。您可能会不小心引入自己的安全漏洞。)
如the documentation所述,每次要发出API请求时,都应调用acquireTokenSilent
。会发生以下三种情况之一:
- 如果 MSAL 在其自己的缓存中有与您提供的参数相匹配的现有令牌,MSAL 将立即提供该令牌。
- 如果需要刷新令牌(例如,因为缓存的访问令牌已过期,或者因为您需要另一个 API 的访问令牌),MSAL 将尝试进行静默令牌刷新。如果此操作无提示地成功,MSAL 将提供新的访问令牌。
- 如果 MSAL 没有缓存的有效访问令牌,并且 MSAL 无法以静默方式刷新它(例如,用户尚未登录、已注销或用户需要同意新权限),然后 MSAL 会通知您,您可以根据需要处理这种情况(例如,使用
acquireTokenPopup
来使用弹出窗口,或使用 acquireTokenRedirect
来使用重定向)。
我是 React 的新手。这个问题是关于在客户端存储身份验证令牌并重复使用它直到到期。
我在我的 React 应用程序中使用 MSAL 进行身份验证。下面是我的代码。
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);
}
};
}
现在,我在 index.js
的 React 路由中使用它:
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 时,withAuth
组件的 componentWillMount
将被调用以检查身份验证。如何确保令牌只生成一次并存储在缓存中并重复使用直到过期?另外,我不确定我是否以正确的方式实施了身份验证。请问有什么帮助吗?
您不必担心令牌的缓存和更新,MSAL 会为您完成这一切。
(事实上,如果您使用的是 MSAL,我特别建议您不要 进行自己的令牌缓存。您可能会不小心引入自己的安全漏洞。)
如the documentation所述,每次要发出API请求时,都应调用acquireTokenSilent
。会发生以下三种情况之一:
- 如果 MSAL 在其自己的缓存中有与您提供的参数相匹配的现有令牌,MSAL 将立即提供该令牌。
- 如果需要刷新令牌(例如,因为缓存的访问令牌已过期,或者因为您需要另一个 API 的访问令牌),MSAL 将尝试进行静默令牌刷新。如果此操作无提示地成功,MSAL 将提供新的访问令牌。
- 如果 MSAL 没有缓存的有效访问令牌,并且 MSAL 无法以静默方式刷新它(例如,用户尚未登录、已注销或用户需要同意新权限),然后 MSAL 会通知您,您可以根据需要处理这种情况(例如,使用
acquireTokenPopup
来使用弹出窗口,或使用acquireTokenRedirect
来使用重定向)。