使用angular-auth-oidc-client的silentRenew时access token偶现null问题求助
问题原因
你用withLatestFrom获取accessToken的方式存在时序问题。withLatestFrom会在事件触发的瞬间取getAccessToken()的当前最新值,但NewAuthenticationResult事件的触发时机可能早于服务内部更新accessToken的时机——也就是说,事件来了,但token还没存到服务里,这时候拿到的就是null;如果事件触发时token已经更新完成,就能拿到有效值,所以才会出现行为不一致的情况。
解决方案
有几种靠谱的处理方式,选一种适合你的即可:
1. 直接从事件结果里拿token
AuthStateResult本身就包含了最新的accessToken,不用额外调用getAccessToken():
this.eventService.registerForEvents().pipe( filter(notification => notification.type === EventTypes.NewAuthenticationResult && (notification.value as AuthStateResult)?.isAuthenticated ), map(notification => (notification.value as AuthStateResult).accessToken) ) .subscribe(accessToken => { console.log('New access token:', accessToken); // 这里的accessToken就是最新的有效token });
2. 用switchMap替代withLatestFrom
如果一定要通过getAccessToken()获取,用switchMap在事件触发后重新订阅最新的token值,而不是取触发瞬间的旧值:
this.eventService.registerForEvents().pipe( filter(notification => notification.type === EventTypes.NewAuthenticationResult && (notification.value as AuthStateResult)?.isAuthenticated ), switchMap(() => this.oidcSecurityService.getAccessToken()) ) .subscribe(accessToken => { console.log('New access token:', accessToken); });
switchMap会在事件触发后重新订阅getAccessToken(),确保拿到的是更新后的token值。
3. 直接订阅认证状态
可以跳过事件监听,直接订阅服务的认证状态流,这样每次状态变化(包括token更新)都会收到通知,且状态是完整更新后的:
this.oidcSecurityService.authState$.pipe( filter(state => state.isAuthenticated), map(state => state.accessToken) ) .subscribe(accessToken => { console.log('Current access token:', accessToken); });
这种方式更简洁,不需要自己处理事件过滤,服务内部会确保状态更新完成后再发出通知。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

