Oidc-client identityserver бесконечный цикл приложение angular 10 при перенаправлении входа

У меня есть приложение 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 пользователь сервера идентификации назначается пользователю свойства.

auth-service.ts

ВОПРОС: после того, как сервер идентификации аутентифицируется и отправляет нам обратно пользователя, страница signin-callback.html затем перенаправляется на / admin, и здесь служба authguardservice запускается снова и пытается проверить, вошел ли пользователь в систему. , вызвав метод isLoggedIn() службы аутентификации. (как видно ниже)  auth-guard-serve

Единственное, что делает метод isLoggedIn(), это проверка, является ли объект user нулевым или нет. и я удивлен, что это null :( хотя мы недавно установили его значение в конструкторе authservice

    isLoggedIn(): boolean{
        return this.user != null && !this.user.expired;
    }

the-issue

И это приводит к нашему знаменитому бесконечному циклу (KMN). Вы также можете предложить ссылку, потому что с этой проблемой сталкивались многие люди, и я дам вам знать, работает ли эта ссылка для меня.


person Tumelo    schedule 17.03.2021    source источник


Ответы (1)


Мне удалось получить некоторую помощь от @brockallen из GitHub.

все, что я сделал, это зашел в sessionStorage и получил оттуда пользователя. и больше никакого бесконечного цикла

    isLoggedIn(): boolean{
        this.user = JSON.parse(sessionStorage.getItem("oidc.user")) as User;
        return this.user != null && !this.user.expired;
    }
person Tumelo    schedule 19.03.2021