Я столкнулся с проблемой с пакетом angular-auth-oidc-client в моем приложении Angular 14, связанной с поведением автоматического входа в систему при открытии новой вкладки. Хотя сам процесс аутентификации, похоже, работает правильно, существует проблема с поведением перенаправления после автоматического входа в систему.
Библиотека: angular-auth-oidc-client
Сценарий:
Пользователь авторизуется на главной вкладке приложения. Пользователь открывает новую вкладку и переходит непосредственно на определенную страницу, например «Моя учетная запись». Ожидаемое поведение: После автоматического входа пользователь должен быть перенаправлен на запрошенную страницу, в данном случае «мой аккаунт».
Фактическое поведение: Вместо перенаправления на запрошенную страницу («мой аккаунт») приложение перенаправляет пользователя обратно на исходную страницу (например, домашнюю).
Такое поведение не идеально для взаимодействия с пользователем, поскольку оно нарушает намеченный поток навигации внутри приложения.
*- Вопрос:- *
Любые идеи или предложения будут с благодарностью приняты. Спасибо!
Я попытался реализовать AutoLoginPartialRoutesGuard для обработки перенаправления, но это не решило проблему. Мне нужна помощь в том, как правильно настроить AutoLoginPartialRoutesGuard или любой другой подход, чтобы гарантировать перенаправление пользователей на нужную страницу после автоматического входа в систему, особенно при открытии новой вкладки.
Файл маршрута
RouterModule.forRoot([
{
path: '',
canActivate: [AuthorizationGuard],
component: MainComponent,
children: [
{
path: '',
redirectTo: 'overview',
pathMatch: 'full'
},
{
path: 'orders',
loadChildren: () => import('./modules/orders/orders.module').then(m => m.OrdersModule),
canActivate: [AutoLoginPartialRoutesGuard],
},
{
path: '**',
redirectTo: ''
}
]
}
], {
useHash: environment.hashRouting,
scrollPositionRestoration: 'enabled'
})
Конфигурация аутентификации
export const httpLoaderFactory = () => {
const authOptions$: Observable<OpenIdConfiguration> = config$.pipe(
map((authOptions: AuthOptions) => {
return {
authority: authOptions.authEndpoint,
redirectUrl: 'https://localhost:3000',
postLogoutRedirectUri: 'https://localhost:3000',
clientId: authOptions.spaClientId,
scope: 'openid profile offline_access',
responseType: 'code',
secureRoutes: [authOptions.apiEndpoint, authOptions.authEndpoint],
silentRenew: true,
useRefreshToken: true,
ignoreNonceAfterRefresh: true,
automaticSilentRenew: true,
disableIdTokenValidation: true,
autoUserInfo: false
} as OpenIdConfiguration;
})
);
return new StsConfigHttpLoader(authOptions$);
};
Аутентификация
export class AuthorizationGuard implements CanActivate {
constructor(private authService: AuthService) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
return this.authService.isAuthorized().pipe(
map(isAuthorized => {
if (!isAuthorized) this.authService.authorize();
return isAuthorized;
})
);
}
}
🤔 А знаете ли вы, что...
Angular обладает многими инструментами и рекомендациями по безопасности приложений.
Чтобы решить проблему, с которой вы столкнулись, вы можете использовать два подхода:
1. Использование AutoLoginPartialRoutesGuard:
Это предполагает использование AutoLoginPartialRoutesGuard из angular-auth-oidc-client в двух местах. Во-первых, вам необходимо включить его в свои маршруты, как показано выше. Во-вторых, вам нужно использовать его в качестве защиты в вашем приложении Angular.
import { AutoLoginPartialRoutesGuard } from 'angular-auth-oidc-client';
constructor(
.....
private autoLoginPartialRoutesGuard: AutoLoginPartialRoutesGuard
.....) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise < boolean | UrlTree > {
return this.authService.isAuthorized().pipe(
switchMap(isAuthorized => {
return this.autoLoginPartialRoutesGuard.canActivate(route, state).pipe(
map(() => {
if (!isAuthorized) this.authService.authorize();
return isAuthorized;
})
);
})
)}
Эта реализация решит вашу проблему.
2. Использование кастомного хранилища из библиотеки:
По умолчанию пакет настроен на использование хранилища сеансов, которое может не сохранять состояние на вкладках. Вместо этого вы можете использовать локальное хранилище для решения проблемы. Для этого вам необходимо создать сервис, как указано в документации.
Пример :
import { Injectable } from "@angular/core";
import { AbstractSecurityStorage } from "angular-auth-oidc-client";
@Injectable()
export class LocalStorageManagerService implements AbstractSecurityStorage {
read(key: string) {
return localStorage.getItem(key);
}
write(key: string, value: any): void {
localStorage.setItem(key, value);
}
remove(key: string): void {
localStorage.removeItem(key);
}
clear(): void {
localStorage.clear();
}
}
Затем вам необходимо включить эту услугу в поставщиков вашего модуля.
providers: [
{
provide: AbstractSecurityStorage,
useClass: LocalStorageManagerService
},
.....
]
Реализация этого решения поможет решить вашу проблему.
Спасибо за прочтение