Окно авторизации из библиотеки @ascon/polynom-login
Библиотека @ascon/polynom-login предоставляет готовое окно авторизации в ПОЛИНОМ:MDM. Окно
выполняет полный сценарий входа: выбор зарегистрированного хранилища, вход по имени входа и паролю,
вход от системной учётной записи, вход по внешнему токену доступа и через общий сервис авторизации
(ОСА). Последние использованные данные сохраняются в локальном хранилище браузера.
См. пример SDK/Web/Samples/Client/polynom-select-demo — в нём окно подключено на отдельном
маршруте sign-in и используется для входа перед открытием диалогов выбора.
Состав библиотеки
Библиотека экспортирует:
AuthenticationPageComponent— готовая страница авторизации (selector: mdm-authentication-page), размещается на маршруте;AuthenticationViewComponent— встраиваемая форма авторизации (selector: mdm-authentication-view) с входными параметрамиaccessTokenиstorageId;AuthenticationLocalStorage— сервис сохранения последнего выбранного хранилища и режима входа;loginValidator,passwordValidator,newPasswordValidatorиspecialSymbolsLabel— валидаторы и подпись допустимых символов для форм;polynomLoginLocalizationScope— область локализацииpolynom/polynom-login.
Подключение библиотек
Рекомендуемые зависимости:
{
"dependencies": {
"@ascon/core": "24.1.126",
"@ascon/polynom-api": "~24.1.14404",
"@ascon/polynom-api-client": "~24.1.14404",
"@ascon/polynom-integration": "~24.1.14404",
"@ascon/polynom-login": "~24.1.14404",
"@ascon/polynom-ui": "~24.1.14404",
"@ascon/primeng": "24.0.2",
"@ascon/qwebchannel-bridge": "^6.8.3",
"@ascon/ui": "24.1.126"
}
}
Библиотеки @ascon/* можно получить из каталога поставки SDK/Web/Samples/Client/libs/@ascon
или из npm-регистра.
Подключение активов и стилей
В файл project.json добавьте активы и стили библиотеки (аналогично примеру
SDK/Web/Samples/Client/polynom-select-demo):
{
"targets": {
"build": {
"options": {
"assets": [
{
"glob": "**/*",
"input": "node_modules/@ascon/polynom-login/assets",
"output": "./assets"
},
{
"glob": "**/*",
"input": "node_modules/@ascon/polynom-ui/assets",
"output": "./assets"
}
],
"styles": [
{
"input": "node_modules/@ascon/theme/theme.css",
"inject": false,
"bundleName": "theme"
},
{
"input": "node_modules/@ascon/polynom-login/styles/polynom-login.css",
"inject": true,
"bundleName": "app-styles"
},
{
"input": "node_modules/@ascon/polynom-ui/styles/polynom-ui.css",
"inject": true,
"bundleName": "app-styles"
}
]
}
}
}
}
Полный пример подключения активов приведён в статье Выбор объекта из ПОЛИНОМ:MDM.
В файл index.html добавьте ссылки на собранные стили:
<html lang="ru">
<head>
<link
href="theme.css"
id="theme-link"
media="all"
onload="this.media='all'"
rel="stylesheet"
type="text/css"
/>
<link
href="app-styles.css"
id="app-link"
media="all"
onload="this.media='all'"
rel="stylesheet"
type="text/css"
/>
</head>
</html>
Настройка приложения
В app.config подключите HTTP-клиент с интерцептором, локализацию (включая область
polynom/polynom-login), начальное обновление токена и маршрутизацию:
// app.config.ts
import { APP_BASE_HREF } from "@angular/common";
import { provideHttpClient, withInterceptors } from "@angular/common/http";
import { APP_INITIALIZER, ApplicationConfig, isDevMode } from "@angular/core";
import { provideAnimations } from "@angular/platform-browser/animations";
import { provideRouter } from "@angular/router";
import { provideLocalization, provideStorages } from "@ascon/core";
import { AuthStore, LoginService, PolynomApiConfig } from "@ascon/polynom-api";
import { IntegrationHostService } from "@ascon/polynom-integration";
import { appInitializer } from "./helpers/app.initializer";
import { jwtInterceptor } from "./helpers/jwt.interceptor";
import { appRoutes } from "./app.routes";
export const appConfig: ApplicationConfig = {
providers: [
provideAnimations(),
provideHttpClient(withInterceptors([jwtInterceptor])),
provideStorages(),
provideLocalization({
availableLangs: ["ru", "en"],
defaultLang: "ru",
prodMode: !isDevMode(),
scopes: [
"polynom/polynom-select-demo",
"polynom/polynom-api",
"polynom/polynom-login",
"polynom/polynom-ui",
"polynom/polynom-core"
]
}),
{ provide: APP_BASE_HREF, useValue: "/select-demo" },
{
provide: APP_INITIALIZER,
useFactory: appInitializer,
deps: [LoginService, PolynomApiConfig, AuthStore],
multi: true
},
provideRouter(appRoutes)
]
};
// helpers/app.initializer.ts
import { LoginService, PolynomApiConfig } from "@ascon/polynom-api";
import { ClientTypes } from "@ascon/polynom-api-client";
import { delay, lastValueFrom, take, TeardownLogic } from "rxjs";
import { environment } from "../environments/environment";
export async function initializeClient(loginService: LoginService): Promise<TeardownLogic> {
await lastValueFrom(loginService.updateToken().pipe(take(1), delay(500)));
}
export function appInitializer(loginService: LoginService, config: PolynomApiConfig): () => Promise<TeardownLogic> {
config.setClientType(ClientTypes.Client);
config.setHost(environment.apiRoute);
return async () => {
try {
return await initializeClient(loginService);
} catch (error) {
console.error("App initialization failed:", error);
}
};
}
// helpers/jwt.interceptor.ts
import { HttpHeaders, HttpInterceptorFn } from "@angular/common/http";
import { inject } from "@angular/core";
import { LoginService } from "@ascon/polynom-api";
export const jwtInterceptor: HttpInterceptorFn = (request, next) => {
const loginService = inject(LoginService);
const polynomAccessToken = loginService.accessToken;
if (polynomAccessToken) {
const clonedRequest = request.clone({
headers: new HttpHeaders({
Authorization: `Bearer ${polynomAccessToken}`
})
});
return next(clonedRequest);
}
return next(request);
};
Адрес web-сервера задаётся сервисом PolynomApiConfig (см.
Авторизация в TypeScript/Angular).
Размещение окна авторизации
AuthenticationPageComponent — standalone-компонент. Разместите его на отдельном маршруте:
// app.routes.ts
import { Route } from "@angular/router";
import { AuthenticationPageComponent } from "@ascon/polynom-login";
import { MainComponent } from "./main/main.component";
export const appRoutes: Route[] = [
{ path: "", redirectTo: "select-example", pathMatch: "full" },
{
path: "",
component: MainComponent,
children: [
{ path: "sign-in", component: AuthenticationPageComponent },
{
path: "select-example",
loadComponent: async () =>
import("./select-example/select-example.component").then(module => module.SelectExampleComponent)
}
]
},
{ path: "**", redirectTo: "select-example", pathMatch: "full" }
];
Переход на окно авторизации выполняется по маршруту sign-in с параметром returnUrl, чтобы после
входа вернуться на исходную страницу:
import { Router } from "@angular/router";
export class AppRouterTools {
public static subRoot(route: string): string {
return `/${route}`;
}
public static navigateTo(router: Router, path: string): void {
router.navigate([AppRouterTools.subRoot(path)], { queryParams: { returnUrl: router.url } }).then();
}
}
Режимы входа
Окно автоматически предоставляет доступные режимы:
- Имя входа и пароль — основной режим для пользователей ПОЛИНОМ:MDM.
- Системная учётная запись — вход без ввода логина и пароля.
- Внешний токен доступа — вход по ранее полученному
accessToken. Режим включается, если компоненту передан входной параметрaccessToken; при этом выбор хранилища фиксируется. - ОСА — вход через общий сервис авторизации. Режим отображается, если web-сервер сообщает о доступности ОСА (см. Авторизация с помощью общего сервиса авторизации).
Встраивание формы авторизации
Если окно на отдельном маршруте не подходит, используйте AuthenticationViewComponent и передайте
ему фиксированное хранилище и токен доступа:
import { Component } from "@angular/core";
import { AuthenticationViewComponent } from "@ascon/polynom-login";
@Component({
selector: "mdm-embedded-sign-in",
standalone: true,
imports: [AuthenticationViewComponent],
templateUrl: "./embedded-sign-in.component.html"
})
export class EmbeddedSignInComponent {
// Идентификатор хранилища, к которому выполняется подключение.
storageId = "f552d8ff-50b1-468e-9577-2069cbaed16e";
// Токен доступа, полученный извне (например, от ОСА). Может быть пустым.
accessToken = "";
}
<mdm-authentication-view [storageId]="storageId" [accessToken]="accessToken"></mdm-authentication-view>
Интеграция в веб-клиент ПОЛИНОМ:MDM
При запуске окна внутри веб-клиента ПОЛИНОМ:MDM идентификатор хранилища и токен доступа передаются
автоматически через IntegrationHostService из @ascon/polynom-integration. В этом случае
AuthenticationPageComponent сам получает значения storageId и accessToken.
Сохранённые данные авторизации
Сервис AuthenticationLocalStorage хранит последнее выбранное хранилище и режим входа:
import { inject } from "@angular/core";
import { AuthenticationLocalStorage } from "@ascon/polynom-login";
private readonly _authDataStorage: AuthenticationLocalStorage = inject(AuthenticationLocalStorage);
// Идентификатор последнего выбранного хранилища.
const lastStorageId: string = this._authDataStorage.lastStorageId;
// Признак входа от системной учётной записи.
const useSystemAccount: boolean = this._authDataStorage.useSystemAccount;
// Признак входа через ОСА.
const useSsoAccount: boolean = this._authDataStorage.useSsoAccount;
// Поток изменения данных авторизации.
this._authDataStorage.authData$.subscribe(data => {
// ...
});
// Сброс сохранённых данных.
this._authDataStorage.reset();
Проверка состояния авторизации и выход
Состояние авторизации и выход выполняются сервисом LoginService:
import { Observable } from "rxjs";
import { LoginService } from "@ascon/polynom-api";
private readonly _loginService: LoginService = inject(LoginService);
get authorized$(): Observable<boolean> {
return this._loginService.authenticated$;
}
signOutHandler(): void {
this._loginService.signOut().pipe(take(1)).subscribe();
}
Возможные ошибки
| Ошибка | Причина | Решение |
|---|---|---|
| Окно авторизации отображается без стилей | Не подключены стили polynom-login.css, polynom-ui.css и theme.css |
Добавьте активы и стили библиотеки в project.json, а ссылки на собранные стили — в index.html |
| Не отображается список хранилищ | Не задан адрес web-сервера или он недоступен | Укажите адрес через PolynomApiConfig.setHost() и проверьте доступность web-сервера |
| Отсутствуют подписи элементов интерфейса | Не подключена область локализации polynom/polynom-login |
Добавьте polynom/polynom-login в массив scopes функции provideLocalization() |
| Не отображается режим входа через ОСА | Web-сервер не сообщает о доступности ОСА | Проверьте настройки ОСА на web-сервере (см. Авторизация с помощью общего сервиса авторизации) |
| Ошибка инициализации приложения при запуске | Не выполнен вход и отсутствует сохранённый токен обновления | Убедитесь, что пользователь перенаправляется на маршрут sign-in, а APP_INITIALIZER обрабатывает ошибку updateToken() |
Связанные статьи
- Авторизация в TypeScript/Angular — программная авторизация
сервисом
LoginServiceи настройка адреса web-сервера. - Авторизация с помощью общего сервиса авторизации — настройка ОСА.
- Выбор объекта из ПОЛИНОМ:MDM — пример приложения, на котором основана статья.