У меня есть приложение angular 10, работающее на localhost: 4200. В моем app-routing.module.ts я настроил корневой путь для загрузки AdminComponent, поэтому, если вы нажмете localhost: 4200, он попытается загрузить AdminComponent, но до того, как это произойдет; У меня есть служба authguard, которая проверяет, вошел ли пользователь в систему, а если нет; он перенаправляет пользователя на сервер идентификации (где он получает экран входа в систему для получения токена).
Я не контролирую поставщика сервера идентификации, он размещен в другой компании
Подключение к IdentityServer4 с потоком кода и PKCE.
Я немного исследовал эту проблему, и многие люди столкнулись с той же проблемой. однако я не смог найти подходящего мне решения. возможно, потому что я новичок в angular и oidc?
https://github.com/damienbod/angular-auth-oidc-client/issues/180
https://github.com/damienbod/angular-auth-oidc-client/issues/829
Бесконечный цикл Oidc-client при вызове signinRedirect
Вот моя установка
app-routing.module.ts
const routes: Routes = [
{ path: 'signout-callback', component: SignoutRedirectCallbackComponent },
{ path: '', component: AdminComponent, canActivate: [AuthGuardService] },
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuardService],
runGuardsAndResolvers: 'pathParamsChange',
resolve: { client: ClientResolver },
children: [
{
path: 'dashboard',
component: DashboardComponent,
resolve: {
client: ClientResolver
}
}
]
},
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes, {scrollPositionRestoration: 'top'})],
exports: [RouterModule]
})
export class AppRoutingModule { }
auth-guard.service.ts
@Injectable()
export class AuthGuardService implements CanActivate{
constructor(private authService:AuthService) { }
canActivate():boolean{
if(this.authService.isLoggedIn()) {
return true;
}
this.authService.startAuthentication();
return false;
}
}
auth.service.ts
@Injectable({
providedIn: 'root'
})
export class AuthService{
private userManager: any;
private user: User = null;
constructor(){
this.userManager = new UserManager(this.getClientSettings());
this.userManager.getUser().then(user =>{
this.user = user;
});
}
isLoggedIn(): boolean{
return this.user != null && !this.user.expired;
}
getClaims(): any{
return this.user.profile;
}
getAuthorizationHeaderValue(): string{
return `${this.user.token_type}${this.user.access_token}`;
}
startAuthentication(): Promise<void>{
return this.userManager.signinRedirect();
}
completeAuthentication(): Promise<void>{
return this.userManager.signinRedirectCallback().then(user =>{
this.user = user;
});
}
public logout(): Promise<void>{
return this.userManager.signoutRedirect();
}
completeLogout(){
this.user = null;
return this.userManager.signoutRedirectCallback();
}
public getUser() : Promise<User>{
return this.userManager.getUser();
}
getUserToken(){
this.userManager.getUser().then(user => {
if(!!user && !user.expired){
console.log(`User : ${user.profile}`);
return user.access_token;
}else{
return null;
}
});
}
getAccessToken(): string {
this.userManager.getUser().then(user =>{
if(!!user && !user.expired){
return user.access_token;
}
});
return this.user.access_token;
}
LoginRedirectHandler(): Promise<any> {
console.log("LoginRedirectHandler");
return this.userManager.getUser().then((user) => {
// avoid page refresh errors
if (user === null || user === undefined) {
return this.userManager.signinRedirectCallback(null);
}
});
}
getClientSettings() : UserManagerSettings{
return {
authority: `${environment.authority}`,
client_id: environment.clientId,
client_secret: environment.clientSecret,
redirect_uri: `${environment.clientRoot}assets/signin-callback.html`,
automaticSilentRenew: true,
silent_redirect_uri: `${environment.clientRoot}assets/silent-callback.html`,
post_logout_redirect_uri: `${environment.clientRoot}signout-callback`,
response_type: 'code',
response_mode: 'query',
scope: environment.clientScope,
filterProtocolClaims: true,
loadUserInfo: false
}
}
}
Когда я запускаю приложение на localhost: 4200, меня сразу перенаправляют на сервер идентификации, что хорошо. Введите адрес электронной почты и пароль, а затем сервер идентификации перенаправит на страницу signin-callback.html.
Пользовательский объект имеет значение id_token, как вы можете видеть здесь, в фрагменте ниже. и это тоже хорошо
И на вкладке сети инструментов разработчика я вижу, что токен находится в разделе ответа, см. Фрагмент ниже. так что пока все хорошо
Также в моем конструкторе auth.service.ts пользователь сервера идентификации назначается пользователю свойства.
ВОПРОС: после того, как сервер идентификации аутентифицируется и отправляет нам обратно пользователя, страница signin-callback.html затем перенаправляется на / admin, и здесь служба authguardservice запускается снова и пытается проверить, вошел ли пользователь в систему. , вызвав метод isLoggedIn()
службы аутентификации. (как видно ниже)
Единственное, что делает метод isLoggedIn()
, это проверка, является ли объект user
нулевым или нет. и я удивлен, что это null :( хотя мы недавно установили его значение в конструкторе authservice
isLoggedIn(): boolean{
return this.user != null && !this.user.expired;
}
И это приводит к нашему знаменитому бесконечному циклу (KMN). Вы также можете предложить ссылку, потому что с этой проблемой сталкивались многие люди, и я дам вам знать, работает ли эта ссылка для меня.