我的应用程序中有以下 AuthProvider:
import { AuthProvider, AuthProviderProps } from 'oidc-react';
const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
const dispatch = useAppDispatch();
const userManagerConfig: AuthProviderProps = {
clientId: 'my_client_id',
responseType: 'code',
redirectUri: `${window.location.protocol}//${window.location.hostname}${
window.location.port ? `:${window.location.port}` : ''
}/callback`,
scope: 'openid profile',
authority: 'my_sso_authority',
silentRedirectUri: `${window.location.protocol}//${
window.location.hostname
}${
window.location.port ? `:${window.location.port}` : ''
}/silent_renew.html`,
automaticSilentRenew: true,
loadUserInfo: true,
autoSignIn: true,
onSignIn: (user: any) => {
console.log('onSignIn', user);
sessionStorage.setItem('token', user.id_token);
dispatch(loadtToken(user.id_token));
}
};
return <AuthProvider {...userManagerConfig}>{children}</AuthProvider>;
};
以及
silent_renew.html
中的以下脚本:
<script type="text/javascript" src=https://cdnjs.cloudflare.com/ajax/libs/oidc-client/1.10.0/oidc-client.js></script>
<script>
new Oidc.UserManager()
.signinSilentCallback()
.then(() => {
console.log('refreshed');
})
.catch(err => {
console.log(err);
});
</script>
登录时,我看到我的
onSignIn
回调工作正常。
但是当访问 silent_renew.html
时,我可以看到最终到达 console.log('refreshed')
语句(顺便说一句,回调中没有参数),但 sessionStorage 中的令牌保持不变。
我尝试将其更改为
new Oidc.UserManager().signinSilent()...
,同时将配置传递给构造函数,但导致了一些错误。
我怀疑我的
silent_renew.html
实际上是正确的。有谁知道它是否应该这样工作?
代码看起来是正确的。由于
automaticSilentRenew
设置,oidc-client 库运行计时器来使用 SSO 会话 cookie 管理令牌刷新。
库查看令牌响应的
expires_in
字段。在访问令牌过期之前,会调用 signInSilent
。这会启动一个隐藏的 iframe,该 iframe 使用 OpenID Connect prompt=none
参数运行代码流。
授权回复
到目前为止,我们已经确定代码流程成功。添加这一行:
console.log(location.href);
您会看到授权代码已正确接收,并带有以下形式的响应:
https://www example.com?code=xxx&state=yyy
iframe 将此 URL 发布到主窗口,从而将代码替换为令牌。
调试
看起来它失败了,所以你需要调试。这可以通过订阅
silentRenewError event
来完成。
失败你可以订阅
。看起来我们在你的案例中失败了
正如所讨论的,在
refresh
行之后添加此行表示您在 iframe 中收到授权代码
代码看起来正确。问题可能是浏览器限制删除了完成此流程所需的授权服务器会话 cookie。这是因为此 cookie 通常是第三方的,因此会被积极删除。
在
refreshed
行之后添加以下行,然后查看授权响应是否包含查询参数 error=login_required
:
console.log(location.href);
如果可以,请在 Safari 浏览器中进行测试,因为此问题最常发生。有关更多信息,请参阅我的这些资源: