我已经用Angular 12.2实现了angular-oauth-oidc (版本12.1.0)。我使用Keycloak作为SSO登录没有问题,但我在库中有一个奇怪的行为。
每次登录后,即使令牌过期,方法hasValidIdToken和hasValidAccessToken也会返回true。似乎库没有验证令牌的过期时间。
我的配置文件如下:
export const authCodeFlowConfig: AuthConfig = {
// Url of the Identity Provider
issuer: 'http://localhost:8080/auth/realms/realmname',
// URL of the SPA to redirect the user to after login
redirectUri: window.location.origin + '/landing',
// The SPA's id. The SPA is registerd with this id at the auth-server
clientId: 'client-name',
responseType: 'code',
// set the scope for the permissions the client should request
// The first four are defined by OIDC.
// Important: Request offline_access to get a refresh token
// The api scope is a usecase specific one
scope: 'openid profile email',
showDebugInformation: true,
};我用以下代码初始化库:
ngOnInit(): void {
this.oauthService.configure(authCodeFlowConfig);
this.oauthService.loadDiscoveryDocumentAndTryLogin().then(() => {
if (this.oauthService.hasValidAccessToken()) {
this.router.navigate(['home']);
}
else {
this.oauthService.initCodeFlow();
}
});
}最后,我在guard中使用以下条件检查令牌是否有效:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot) {
var hasIdToken = this.oauthService.hasValidIdToken();
var hasAccessToken = this.oauthService.hasValidAccessToken();
var hasAccess = (hasIdToken && hasAccessToken)
if (!hasAccess) {
console.log('AuthGuard: Token not valid');
this.router.navigate(['landing']);
}
else {
console.log('AuthGuard: Valid token');
}
return hasAccess;
}如果我以前登录过,这个方法总是返回true。在没有事先登录的情况下,它会按预期返回false。
如果我使用其他库进行令牌验证,则在验证过期令牌时会得到预期的结果。
发布于 2021-11-20 17:56:44
您发布的ngOnInit将是异步的,可能需要150ms才能完成。最有可能的是,你的浏览器在初始化运行之前同步地触发了守卫,因此将返回访问令牌上的存储中的旧状态。
您需要执行以下任一操作:
async APP_INITIALIZER,以确保在加载发现文档和所有make it wait for initialization on auth to be finished之前,应用程序中没有运行任何内容;或者使用
你可以通过快速更改你自己的设置延迟2.5秒来检查我的怀疑是否正确,这样我们就可以合理地确定初始化已经完全完成:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot) {
var hasIdToken = this.oauthService.hasValidIdToken();
var hasAccessToken = this.oauthService.hasValidAccessToken();
var hasAccess = (hasIdToken && hasAccessToken)
return new Promise((resolve) => {
setTimeout(() => {
if (!hasAccess) {
console.log('AuthGuard: Token not valid');
this.router.navigate(['landing']);
} else {
console.log('AuthGuard: Valid token');
}
resolve(hasAccess);
}, 2500);
);
}https://stackoverflow.com/questions/69058026
复制相似问题