我已经使用 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();
}
});
}
最后,我使用守卫中的以下条件检查令牌是否有效:
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
。
如果我使用其他库进行令牌验证,则在验证过期令牌时会得到预期的结果。
您发布的
ngOnInit
将是异步的,可能需要 150 毫秒才能完成。您的浏览器很可能会同步地遇到防护,因此之前初始化已运行,因此将从访问令牌上的存储中返回旧状态。
您需要:
async
APP_INITIALIZER
中进行初始化,以确保在加载发现文档和所有这些爵士乐之前应用程序中没有任何内容运行;或您可以通过快速更改自己的设置以延迟 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);
);
}
我遇到了类似的问题,其中
hasValidAccessToken
错误地为过期令牌返回 true。要解决此问题,请在代码中设置 this.oauthService.clockSkewInSec = 0;
。现在,该方法可以正常工作了。
this.oauthService.clockSkewInSec = 0;
如果这有帮助,请考虑投票。如果您需要进一步的帮助,请告诉我!