我遇到了使用oidc-client进行静默刷新的问题。 登录工作正常,我能够获得一个令牌。 但是,静默刷新不会触发,也不会发生任何事情,当我订阅检查令牌expiracy的方法(authservice.ts中的subscribeevents中的方法)时,这些方法永远不会触发,并且方法isLoggedIn()总是返回true事件,如果令牌已过期!!!!!
有人可以帮助我吗?
这是我的代码:
import { Component, OnInit } from '@angular/core';
import { UserManager } from 'oidc-client';
import { getClientSettings } from '../openIdConnectConfig';
import { AuthService } from '../services/auth.service';
@Component({
selector: 'app-silentrefresh',
templateUrl: './silentrefresh.component.html',
styleUrls: ['./silentrefresh.component.css']
})
export class SilentRefreshComponent implements OnInit {
constructor(private _authService:AuthService) {
}
ngOnInit() {
this._authService.refreshCallBack();
}
}
然后是我的authservice:
import { UserManagerSettings, UserManager, User } from 'oidc-client';
import { Injectable } from '@angular/core';
import { getClientSettings } from '../openIdConnectConfig';
@Injectable()
export class AuthService {
private _manager = new UserManager(getClientSettings());
private _user: User = null;
constructor() {
this._manager.getUser().then(user => {
this._user = user;
});
this._manager.events.addUserLoaded(user => {
this._user = user;
});
this.subscribeevents();
}
public isLoggedIn(): boolean {
return this._user != null && !this._user.expired;
}
public getClaims(): any {
return this._user.profile;
}
public subscribeevents() :void {
this._manager.events.addSilentRenewError(() => {
console.log("error SilentRenew");
});
this._manager.events.addAccessTokenExpiring(() => {
console.log("access token expiring");
});
this._manager.events.addAccessTokenExpired(() => {
console.log("access token expired");
});
}
public refreshCallBack(): void
{
console.log("start refresh callback");
this._manager.signinSilentCallback()
.then(data => {console.log("suucess callback")})
.catch(err => {
console.log("err callback");
});
console.log("end refresh callback");
}
getUser(): any {
return this._user;
}
getName(): any {
return this._user.profile.name;
}
getAuthorizationHeaderValue(): string {
return `${this._user.token_type} ${this._user.access_token}`;
}
startAuthentication(): Promise<void> {
return this._manager.signinRedirect();
}
completeAuthentication(): Promise<void> {
return this._manager.signinRedirectCallback().then(user => {
this._user = user;
});
}
}
我的配置:
import { UserManagerSettings } from "oidc-client";
export function getClientSettings(): UserManagerSettings {
return {
authority: 'https://login.microsoftonline.com/136544d9-038e-4646-afff-10accb370679',
client_id: '257b6c36-1168-4aac-be93-6f2cd81cec43',
redirect_uri: 'http://localhost:4200/auth-callback',
//redirect_uri: 'https://demoazureadconnectangular5.azurewebsites.net/auth-callback',
post_logout_redirect_uri: 'http://localhost:4200/',
//post_logout_redirect_uri: 'https://demoazureadconnectangular5.azurewebsites.net/',
response_type:"id_token",
scope:"openid profile",
filterProtocolClaims: true,
loadUserInfo: true,
automaticSilentRenew: true,
silent_redirect_uri: 'http://localhost:4200/assets/silentrefresh',
metadata: {
issuer: "https://sts.windows.net/136544d9-038e-4646-afff-10accb370679/",
authorization_endpoint: "https://login.microsoftonline.com/136544d9-038e-4646-afff-10accb370679/oauth2/authorize",
token_endpoint: "https://login.microsoftonline.com/136544d9-038e-4646-afff-10accb370679/oauth2/token",
//jwks_uri: "https://login.microsoftonline.com/common/discovery/keys",
jwks_uri: "http://localhost:4200/assets/keys.json",
//jwks_uri: "https://demoazureadconnectangular5.azurewebsites.net/assets/keys.json",
//jwks_uri: "http://localhost:50586/api/keys",
signingKeys: [{"ApiAccessKey": "NgixniZ0S1JHxo7GPEZYa38OBTxSA98AqJKDX5XqsJ8="}]
}
};
}
我还尝试使用这样的静态页面:
<head>
<title></title>
</head>
<body>
<script src="oidc-client.min.js"></script>
<script>
var usermanager = UserManager().signinSilentCallback()
.catch((err) => {
console.log(err);
});
</script>
</body>
它从未被解雇
为了快速测试,我将ID令牌的使用时间设置为10分钟。 我使用Azure AD Connect(Azure中的Open Id Connect),微软表示它与Open ID Connect标准完全兼容....所以我不知道它是在我身边还是在Azure端。
有人可以帮我解决这个问题吗?
答案 0 :(得分:1)
检查数据库中的重定向URI是否正确。
检查是否已添加
“资产”:[ “ src /资产”, “ silent-refresh.html”, “ oidc-client.min.js” ..... ]
检查silent-refresh.html
<script src="oidc-client.min.js"></script><script>
var mgr = new Oidc.UserManager();
mgr.signinSilentCallback().catch(error => {
console.error(error);
});
</script>
检查您是否创建了多个UserManager实例
您可以使用automaticSilentRenew: false
或automaticSilentRenew: true,
的任何一种方式,我建议您使用automaticSilentRenew: false
并在到期时触发事件。
https://github.com/IdentityModel/oidc-client-js/wiki
public renewToken() {
return this.manager.signinSilent().then(u => {
this.user = u;
}).catch(er => {
console.log(er);
});
}
this.manager.events.addAccessTokenExpiring(x => {
console.log('Acess token expiring event');
this.renewToken().then(u => {
console.log('Acess token expiring event renew success');
});
});
如果上述操作不起作用,请检查身份服务器代码。
身份服务器代码 启动
services.AddIdentityServer(options =>
{
options.Authentication.CookieLifetime = TimeSpan.FromDays(30);
options.Authentication.CookieSlidingExpiration = true;
});
services.AddAuthentication(x => x.DefaultAuthenticateScheme = IdentityServerConstants.DefaultCookieAuthenticationScheme);
注销
await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme);
感谢https://github.com/IdentityModel/oidc-client-js/issues/911#issuecomment-617724445
答案 1 :(得分:0)
我使用了一些不同的方法来启动silentRenw,而不是使用
automaticSilentRenew: true,
我决定明确调用signInSilent();. 做i的原因是面临一些问题,因为automaticSilentRenew:true,没有按预期工作。
我在实现我的接口的UserAuth类构造函数中初始化了事件和方法
constructor(private oidcSettings: CoreApi.Interfaces.Authentication.OpenIDConnectionSettings)
{
this.userManager.events.addAccessTokenExpiring(() =>
{
this.userManager.signinSilent({scope: oidcSettings.scope, response_type: oidcSettings.response_type})
.then((user: Oidc.User) =>
{
this.handleUser(user);
})
.catch((error: Error) =>
{
//Work around to handle to Iframe window timeout errors on browsers
this.userManager.getUser()
.then((user: Oidc.User) =>
{
this.handleUser(user);
});
});
});
}
其中handleUser只是检查登录用户。
因此,如果您在构造函数中初始化signInSilent进程,然后调用signInSilent完成,即回调它可能会有效。
答案 2 :(得分:0)
我使用的Azure广告在100%时与开放式ID Connect不完全兼容,我只收到一个ID_token,并且没有OIDC-CLIENT要求的access_token。 我必须切换到Microsoft库ADAL.JS
答案 3 :(得分:0)
Not sure what oidc-client.js version you are using, this should never have worked.
```
new Oidc.UserManager().signinSilentCallback()
.catch((err) => {
console.log(err);
});
``
Usermanager is in **Oidc** object.
答案 4 :(得分:0)
问题是您不是从azure AD询问access_token,仅询问id_token。您必须将response_type设置为id_token令牌才能获取两个令牌。此更改还将需要更多的参数。例如您的后端资源。 我在这里回答了类似的问题。我也在使用Angular 5和oidc客户端。 https://stackoverflow.com/a/50922730/8081009 我也在https://github.com/IdentityModel/oidc-client-js/issues/504#issuecomment-400056662之前在这里回答您 这是您需要设置的功能,以使更新无声工作。
includeIdTokenInSilentRenew: true
extraQueryParams: {
resource: '10282f28-36ed-4257-a853-1bf404996b18'
}
response_type: 'id_token token',
scope: 'openid'
loadUserInfo: false,
automaticSilentRenew: true,
silent_redirect_uri: `${window.location.origin}/silent-refresh.html`,
metadataUrl: 'https://login.microsoftonline.com/YOUR_TENANT_NAME.onmicrosoft.com/.well-known/openid-configuration',
signingKeys: [
add here keys from link below
]
https://login.microsoftonline.com/common/discovery/keys
我还对具有静默更新的回调终结点使用了不同的静态页面,因为这样用户将不会注意到任何事情。该页面的数量最少,因此oidc不会将整个角度应用程序加载到用于静默更新的隐藏iframe中。因此,建议这样做更有效。
<head>
<title></title>
</head>
<body>
<script src="assets/oidc-client.min.js"></script>
<script>
new Oidc.UserManager().signinSilentCallback()
.catch((err) => {
console.log(err);
});
</script>
</body>
答案 5 :(得分:0)
最简单的原因可能是,没有在身份服务器配置中添加静默更新URL作为重定向URL。
在您的身份服务器数据库中,客户端的重定向URL应该是这样的
redirectUrls: [http://localhost:4200/assets/silentrefresh, http://localhost:4200/auth-callback]