让 angular-oauth2-oidc 从其他选项卡检索访问令牌
Have angular-oauth2-oidc retrieve access token from other tabs
我正在使用 angular-oauth2-oidc library in combination with the Implicit Flow (with an IdentityServer4 server). I've successfully set up the Silent Refresh suggestion from the docs。
以下是我 bootstrap 包装服务中的内容:
private userSubject = new Subject<User>();
constructor(private config: ConfigService, private oAuthService: OAuthService)
{ }
// Called on app load:
configure(): void {
const config: AuthConfig = {
issuer: this.config.getIdentityUrl(),
logoutUrl: this.config.getIdentityUrl() + '/connect/endsession',
redirectUri: window.location.origin + '/',
silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html',
clientId: 'my_client_id',
scope: 'openid profile my_api',
sessionChecksEnabled: true,
};
this.oAuthService.configure(config);
this.oAuthService.tokenValidationHandler = new JwksValidationHandler();
this.oAuthService
.loadDiscoveryDocumentAndLogin()
.then((_) => this.loadUserProfile());
this.oAuthService.setupAutomaticSilentRefresh();
}
private loadUserProfile() {
this.oAuthService.loadUserProfile()
.then((userProfile) => {
const user = new User(userProfile['name']);
this.userSubject.next(user);
});
}
但是,如果我在新选项卡中打开应用程序,用户也会被重定向到 IdentityServer(并立即返回到我的应用程序)。
我的问题:我能否让库从同源的其他选项卡检索现有访问令牌(以及可选的用户信息),以防止重定向?(首选,因为它不需要 Ajax 次调用。)
或者,有没有一种简单的方法可以在我们将某人发送到 IdentityServer 之前尝试使用静默刷新机制?
有一个解释,为什么它总是去IdentityServer澄清当前用户,就是你展示的代码。
每次你打开一个标签页,你的应用程序就会启动,上面的代码就会被执行。现在 - 所有这些支持 SPA'a 和 Implicit
流程的 oidc 库都将用户数据(access_token
...)存储在浏览器会话存储中。通过打开一个新选项卡,您将拥有一个新会话。
我的观点是 - 在尝试针对 Identity Server 进行身份验证之前,您需要做一些事情。我指的是将所有用户信息从 Session storage
移动到 Local storage
。然后,位于同一应用程序(分别为同一来源)下的选项卡将共享 Local storage
.
所以您在应用启动时的流程应该类似于:
- 检查用户信息的本地存储
- 如果存在,请设置身份验证服务(包括静默刷新),但不要尝试登录。并将数据移动到会话存储(不确定是否需要,但我猜图书馆会在那里寻找它)
- 如果不是-登录,然后将数据从会话存储移动到本地
- 当然,在静默更新回调中,您必须更新本地存储中的值(它们应该由库在会话中更新)。
- 最后但同样重要的是 - 在注销时,您必须进行清理。
对我来说,这似乎是适合您的解决方案。现在 - 由您来决定开销是否值得。
PS:澄清一下——我还没有试过。我不能保证它会起作用,但按照事件的顺序,它应该会起作用。
首先:我以某种方式想到 sessionStorage
适合代币,localStorage
应该 总是 避免。但那是来自另一个涉及更强大(刷新)令牌的项目,并且通过隐式流程我只有短暂的访问令牌所以 localStorage
也不是 that 比 更不安全sessionStorage
。最后:根据您自己的具体情况评估攻击媒介:“视情况而定”。
我没有提到我有那个想法, 帮助我重新思考并考虑使用 localStorage。这实际上是一个很好的解决方案。
事实证明,该库内置了对使用 localStorage
作为令牌和其他数据的后备存储的支持。起初虽然我在尝试:
// This doesn't work properly though, read on...
this.oAuthService.setStorage(localStorage);
但是这种引导方式对我的情况不起作用,请参阅 issue 321 on the libraries GitHub issues list 以了解我的日志。从该线程重复解决方案(或解决方法?),我通过在应用程序模块的 providers
:
中执行此操作解决了问题
{ provide: OAuthStorage, useValue: localStorage },
现在图书馆将正确使用 localStorage 并且新选项卡(甚至新的 windows)将自动选择它。
作为脚注,如果您出于安全原因不想使用 localStorage
,您也可以提供自己的存储,只要它实现了 OAuthStorage
接口。然后,您自己的实现可以使用任何可用的选项卡间通信技术来“询问”来自其他选项卡的数据,并在需要时回退到 sessionStorage。
在应用程序中 module.ts
export function oAuthStorageFactory(): OAuthStorage {
return localStorage;}
@NgModule({ .. })
providers: [
{ provide: OAuthStorage,
useFactory: oAuthStorageFactory
}
]
此配置会将令牌保存在本地存储中,而不是将其保存在默认会话中。
我正在使用 angular-oauth2-oidc library in combination with the Implicit Flow (with an IdentityServer4 server). I've successfully set up the Silent Refresh suggestion from the docs。
以下是我 bootstrap 包装服务中的内容:
private userSubject = new Subject<User>();
constructor(private config: ConfigService, private oAuthService: OAuthService)
{ }
// Called on app load:
configure(): void {
const config: AuthConfig = {
issuer: this.config.getIdentityUrl(),
logoutUrl: this.config.getIdentityUrl() + '/connect/endsession',
redirectUri: window.location.origin + '/',
silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html',
clientId: 'my_client_id',
scope: 'openid profile my_api',
sessionChecksEnabled: true,
};
this.oAuthService.configure(config);
this.oAuthService.tokenValidationHandler = new JwksValidationHandler();
this.oAuthService
.loadDiscoveryDocumentAndLogin()
.then((_) => this.loadUserProfile());
this.oAuthService.setupAutomaticSilentRefresh();
}
private loadUserProfile() {
this.oAuthService.loadUserProfile()
.then((userProfile) => {
const user = new User(userProfile['name']);
this.userSubject.next(user);
});
}
但是,如果我在新选项卡中打开应用程序,用户也会被重定向到 IdentityServer(并立即返回到我的应用程序)。
我的问题:我能否让库从同源的其他选项卡检索现有访问令牌(以及可选的用户信息),以防止重定向?(首选,因为它不需要 Ajax 次调用。)
或者,有没有一种简单的方法可以在我们将某人发送到 IdentityServer 之前尝试使用静默刷新机制?
有一个解释,为什么它总是去IdentityServer澄清当前用户,就是你展示的代码。
每次你打开一个标签页,你的应用程序就会启动,上面的代码就会被执行。现在 - 所有这些支持 SPA'a 和 Implicit
流程的 oidc 库都将用户数据(access_token
...)存储在浏览器会话存储中。通过打开一个新选项卡,您将拥有一个新会话。
我的观点是 - 在尝试针对 Identity Server 进行身份验证之前,您需要做一些事情。我指的是将所有用户信息从 Session storage
移动到 Local storage
。然后,位于同一应用程序(分别为同一来源)下的选项卡将共享 Local storage
.
所以您在应用启动时的流程应该类似于:
- 检查用户信息的本地存储
- 如果存在,请设置身份验证服务(包括静默刷新),但不要尝试登录。并将数据移动到会话存储(不确定是否需要,但我猜图书馆会在那里寻找它)
- 如果不是-登录,然后将数据从会话存储移动到本地
- 当然,在静默更新回调中,您必须更新本地存储中的值(它们应该由库在会话中更新)。
- 最后但同样重要的是 - 在注销时,您必须进行清理。
对我来说,这似乎是适合您的解决方案。现在 - 由您来决定开销是否值得。
PS:澄清一下——我还没有试过。我不能保证它会起作用,但按照事件的顺序,它应该会起作用。
首先:我以某种方式想到 sessionStorage
适合代币,localStorage
应该 总是 避免。但那是来自另一个涉及更强大(刷新)令牌的项目,并且通过隐式流程我只有短暂的访问令牌所以 localStorage
也不是 that 比 更不安全sessionStorage
。最后:根据您自己的具体情况评估攻击媒介:“视情况而定”。
我没有提到我有那个想法,
事实证明,该库内置了对使用 localStorage
作为令牌和其他数据的后备存储的支持。起初虽然我在尝试:
// This doesn't work properly though, read on...
this.oAuthService.setStorage(localStorage);
但是这种引导方式对我的情况不起作用,请参阅 issue 321 on the libraries GitHub issues list 以了解我的日志。从该线程重复解决方案(或解决方法?),我通过在应用程序模块的 providers
:
{ provide: OAuthStorage, useValue: localStorage },
现在图书馆将正确使用 localStorage 并且新选项卡(甚至新的 windows)将自动选择它。
作为脚注,如果您出于安全原因不想使用 localStorage
,您也可以提供自己的存储,只要它实现了 OAuthStorage
接口。然后,您自己的实现可以使用任何可用的选项卡间通信技术来“询问”来自其他选项卡的数据,并在需要时回退到 sessionStorage。
在应用程序中 module.ts
export function oAuthStorageFactory(): OAuthStorage {
return localStorage;}
@NgModule({ .. })
providers: [
{ provide: OAuthStorage,
useFactory: oAuthStorageFactory
}
]
此配置会将令牌保存在本地存储中,而不是将其保存在默认会话中。