Авторизация в TypeScript/Angular
ВНИМАНИЕ: применяемость токена входа истекает через 10 минут после его создания. Для продолжения работы нужно использовать токен обновления.
Создание Http-клиента
// В модуле
// Импортируем класс клиента
import { HttpClient, HttpHeaders } from "@angular/common/http";
// Получаем адрес сервера
export const polynomWebApiAddress = "http://localhost:5000";
export function url(value: string, customApiVersion?: number): string {
const host = polynomWebApiAddress;
if (host) {
const defaultVersion = 1;
const version = customApiVersion ? customApiVersion : defaultVersion;
return `${host}/api/v${version}${value}`;
}
return value;
}
// Объявить
export const POLYNOM_STORAGE_ID = "polynom-storage-id";
export const POLYNOM_ACCESS_TOKEN = "polynom-access-token";
export const POLYNOM_REFRESH_TOKEN = "polynom-refresh-token";
// В классе
// В конструкторе получаем экземпляр класса HttpClient
constructor(private readonly _http: HttpClient) { }
Получение списка зарегистрированных хранилищ
Определение IStorageDefinition
export type IStorageDefinition = {
storageId: string;
displayName: string;
};
Запрос и чтение ответа:
/*Возвращает данные пользователя*/
this._http
.get<IStorageDefinition[]>(url("/login/storage-definitions"))
.pipe(take(1))
.subscribe({
next: (response) => {
// Выбрать нужное хранилище из списка
},
error: (err) => {
// Обработка ошибки
},
});
Вход
Определение SignInRequest
// Тип клиента API.
export enum ClientTypes {
// Нет типа.
None = 0,
// Клиент.
Client = 8,
// Конвертер.
Importer = 16,
// Редактор.
Editor = 32,
// Администратор.
Administrator = 64,
}
export type ISignInRequest = {
// Идентификатор хранилища
storageId: string;
// Имя пользователя ПОЛИНОМ:MDM
login?: string;
// Пароль
password?: string;
// Пароль
moduleName?: string;
// Указывает тип клиента.
clientType?: ClientTypes;
};
Определение AuthResponse
export type IAuthResponse = {
// Токен доступа.
access_token: string;
// Тип токена доступа.
token_type: string;
// Срок жизни токена доступа. (сек.)
expires_in: number;
// Токен обновления токена доступа.
refresh_token: string;
};
Запрос и чтение ответа:
const request: ISignInRequest = {
login: username,
password: password,
storageId: storageId,
clientType: ClientType.Client,
};
this._http
.post<IAuthResponse>(url("/login/sign-in"), request)
.pipe(take(1))
.subscribe({
next: (response) => {
// Сохранить полученные ключи и идентификтаор хранилища для использования в запросах
const storage: Storage = window.localStorage;
storage.setItem(POLYNOM_STORAGE_ID, request.storageId);
storage.setItem(POLYNOM_ACCESS_TOKEN, response.access_token);
storage.setItem(POLYNOM_REFRESH_TOKEN, response.refresh_token);
},
error: (err) => {
// Обработка ошибки
},
});
Использование токена в запросах к API
Чтобы отправлять запросы web-серверу ПОЛИНОМ:MDM, нужно добавить полученный ранее токен доступа и идентифмкатор хранилища в заголовок запроса.
import { HttpHeaders, HttpInterceptorFn } from "@angular/common/http";
export const jwtInterceptor: HttpInterceptorFn = (request, next) => {
const storage: Storage = window.localStorage;
// Получаем токен авторизации из хранилища
const polynomAccessToken = storage.getItem(POLYNOM_ACCESS_TOKEN);
if (polynomAccessToken) {
// Получаем идентификатор хранилища ПОЛИНОМ:MDM
const polynomStorageId = storage.getItem(POLYNOM_STORAGE_ID);
if (!polynomStorageId) {
return next(request);
}
const clonedRequest = request.clone({
headers: new HttpHeaders({
"X-Polynom-Storage-Id": polynomStorageId,
Authorization: `Bearer ${polynomAccessToken}`,
}),
});
return next(clonedRequest);
}
return next(request);
};
Обновление токена входа
Запрос и чтение ответа:
const storage: Storage = window.localStorage;
// Получаем идентификатор хранилища ПОЛИНОМ:MDM
const polynomStorageId = storage.getItem(POLYNOM_STORAGE_ID);
if (!polynomStorageId) {
return;
}
// Получаем ключ авторизации из хранилища
const polynomAccessToken = storage.getItem(POLYNOM_ACCESS_TOKEN);
if (!polynomAccessToken) {
return;
}
// Получаем ключ обновления ключа авторизации из хранилища
const polynomRefreshToken = storage.getItem(POLYNOM_REFRESH_TOKEN);
if (!polynomRefreshToken) {
return;
}
let header = new HttpHeaders({
"Content-Type": "text/plain",
"X-Polynom-Storage-Id": polynomStorageId,
Authorization: `Bearer ${polynomAccessToken}`,
});
this._http
.patch<IAuthResponse>(url("/login/update-token"), polynomRefreshToken, {
headers: header,
})
.pipe(take(1))
.subscribe({
next: (response) => {
// Сохранить полученные ключи и идентификатор хранилища для использования в запросах
const storage: Storage = window.localStorage;
storage.setItem(POLYNOM_ACCESS_TOKEN, response.access_token);
storage.setItem(POLYNOM_REFRESH_TOKEN, response.refresh_token);
},
error: (err) => {
// Обработка ошибки
},
});
Выход
Запрос и чтение ответа:
this._http
.delete<void>(url("/login/sign-out")
.pipe(take(1))
.subscribe({
next: () => {
// Сохранить полученные ключи и идентификатор хранилища для использования в запросах
const storage: Storage = window.localStorage;
storage.removeItem(POLYNOM_STORAGE_ID);
storage.removeItem(POLYNOM_ACCESS_TOKEN);
storage.removeItem(POLYNOM_REFRESH_TOKEN);
},
error: (err) => {
// Обработка ошибки
},
});