@it-enterprise/jwtauthentication
v3.2.0
Published
JSON Web Token-Based authentication library
Readme
@it-enterprise/jwtauthentication
@it-enterprise/jwtauthentication — це клієнтська бібліотека для роботи з автентифікацією та авторизацією за схемою Token-Based Authentication з використанням стандарту JSON Web Tokens.
Токени є засобом авторизації для кожного запиту від клієнта до сервера.
Токени генеруються на сервері на основі секретного ключа, що зберігається на сервері.
Токен зберігається на клієнті та використовується при необхідності авторизації будь-якого запиту.
JSON Web Tokens
JSON Web Token (JWT) — містить три блоки, розділених крапками: заголовок (header), набір полів (payload) та сигнатуру. Перші два блоки представлені у форматі JSON і додатково закодовані у формат base64. Набір полів містить довільні пари ім'я/значення, при цьому стандарт JWT визначає кілька зарезервованих імен (iss, aud, exp та інші).
Принцип роботи:
Для авторизації використовується логін/пароль і fingerprint.
Що таке fingerprint? Це інструмент ідентифікації браузера — згенерований хеш на основі унікальних параметрів браузера (userAgent, мова, роздільна здатність екрана тощо). Fingerprint ніде персистентно не зберігається і генерується лише в момент входу та оновлення токена.
...таким чином:
- Користувач входить у застосунок, передаючи логін/пароль і fingerprint
- Сервер перевіряє автентичність логіна/пароля
- У разі успіху створює та записує сесію в БД
- Надсилає клієнту два токени — access та refresh token
"accessToken": "eyJhbGciOiJIUzI1NiIs...""refreshToken": "9f34dd3a-ff8d-43aa-b286-9f22555319f6" - Бібліотека зберігає токени, використовуючи access token для подальшої авторизації запитів
access token — використовується для авторизації запитів та зберігання інформації про користувача.
refresh token — видається сервером за результатами успішної автентифікації і використовується для отримання нової пари access/refresh токенів.
Кожен токен має свій термін дії: access — 30 хв, refresh — 60 днів.
Перед кожним запитом бібліотека попередньо перевіряє час дії access token'а і, якщо він закінчився, використовує refresh token для оновлення обох токенів.
Встановлення
npm install @it-enterprise/jwtauthenticationПідключення
// main.js
import auth from '@it-enterprise/jwtauthentication'Конфігурування
Налаштування передаються об'єктом у метод config:
auth.config({ baseUrl: 'https://m.it.ua/GraphQlServer/' })Якщо baseUrl відносний, адреса хоста буде взята з window.location.origin:
// При запуску на локальній машині отримаємо http://localhost:8080/ForceBPM/GraphQlServer/
auth.config({ baseUrl: 'ForceBPM/GraphQlServer' })Параметри конфігурації
| Параметр | Тип | Обов'язковий | Опис |
|---|---|---|---|
| baseUrl | string | ✓ | Абсолютний або відносний шлях до сервера |
| webUrl | string | | Базовий URL веб-застосунку (використовується для OIDC redirect URI) |
| onError | function(error) | | Обробник помилок серверних запитів |
| onBeforeLogin | function | | Викликається перед кожним запитом на вхід |
| onBeforeRefresh | function(refreshToken, fingerprint) | | Викликається перед кожним запитом на оновлення токена |
| onAfterRefresh | function | | Викликається після оновлення токена |
| oidc | object | | Конфігурація OpenID Connect: { authority, client, addScope } |
| getLang | function | | Функція, що повертає поточну мову (додається до заголовка Accept-Language) |
| logger | object | | Кастомний логер (за замовчуванням console) |
| fingerprint | string | | Кастомний fingerprint браузера |
| returnOidcToken | boolean | | Повертати OIDC токен напряму, без обміну на внутрішній |
| needLockRefreshToken | boolean | | Блокувати паралельні запити на refresh (очікувати завершення поточного) |
| validateTokenBasedOnClientTime | boolean | | Валідувати токен за часом клієнта, а не сервера |
| closeSessionAutomatically | boolean | | Автоматично завершувати сесію після 15 хвилин неактивності |
| afterSignOutAction | function | | Викликається після автоматичного виходу |
| useCookieForTokens | boolean | | Використовувати cookie замість JWT для зберігання сесії |
| useServerRememberMe | boolean | | Делегувати логіку "запам'ятати мене" на сервер |
| silentRequestTimeoutInSeconds | number | | Таймаут silent-запиту OIDC (за замовчуванням 10) |
| skipCheckLicense | boolean | | Пропускати перевірку ліцензії |
| loginUrl | string | | Перевизначити URL входу (за замовчуванням api/authentication/login) |
| logoutUrl | string | | Перевизначити URL виходу (за замовчуванням api/authentication/logout) |
| refreshUrl | string | | Перевизначити URL оновлення токена (за замовчуванням api/authentication/refresh) |
| authTypesUrl | string | | Перевизначити URL отримання типів автентифікації |
| closeSessionUrl | string | | Перевизначити URL закриття сесії |
// Приклад повної конфігурації
auth.config({
baseUrl: window.myConfig.GraphQlUrl,
webUrl: window.location.origin + '/',
onError: e => {
if (e.response && e.response.status === 401) {
store.dispatch('auth/logout')
}
},
onBeforeRefresh: (refreshToken, fingerprint) => {
console.log('оновлення токена...', fingerprint)
},
needLockRefreshToken: true,
closeSessionAutomatically: true
})API
getAllowedAuthTypes (async)
Запитує доступні способи входу в систему.
auth.getAllowedAuthTypes()
// return
{
AllowedAuthTypes: 'Sms,Email,Google,Facebook,SmartId,DigitalCertificate'
}login (async)
Стандартний вхід із використанням логіна та пароля.
auth.login(login, password, rememberMe, needCheckUserGroup)
// return
{
success: true,
errorMessage: '',
TempPasswordMessage: '', // повідомлення про тимчасовий пароль
TempPasswordRequired: false, // потрібне підтвердження тимчасовим паролем
NeedChangePassword: false // потрібна зміна пароля
}| Параметр | Тип | Обов'язковий | Опис |
|---|---|---|---|
| login | string | ✓ | Логін користувача |
| password | string | ✓ | Пароль |
| rememberMe | boolean | | Запам'ятати користувача (зберегти refresh token у cookie) |
| needCheckUserGroup | boolean | | Перевіряти належність користувача до групи |
confirmCode (async)
Підтверджує код двофакторної автентифікації (2FA).
auth.confirmCode('123456')
// return
{
success: true/false,
errorMessage: ''
}loginBySMS (async)
Ініціює вхід через SMS — надсилає одноразовий пароль на вказаний номер телефону.
auth.loginBySMS('+380991234567')
// return
{
success: true/false,
errorMessage: ''
}enterOneTimeSMSPassword (async)
Завершує вхід через SMS, передаючи отриманий одноразовий пароль.
auth.enterOneTimeSMSPassword('tmpPass')
// return
{
success: true/false,
errorMessage: ''
}loginByCode (async)
Вхід із використанням QR-коду.
auth.loginByCode('code')
// return
{
success: true/false,
errorMessage: ''
}loginByPINCode (async)
Вхід із використанням PIN-коду.
auth.loginByPINCode('1234')
// return
{
success: true/false,
errorMessage: ''
}loginByBarCode (async)
Вхід із використанням штрих-коду.
auth.loginByBarCode('code')
// return
{
success: true/false,
errorMessage: ''
}loginByDigitalSignature (async)
Вхід із використанням цифрового підпису.
auth.loginByDigitalSignature('sign')
// return
{
success: true/false,
errorMessage: ''
}getAuthGuid (async)
Отримати GUID для автентифікації за цифровим підписом. GUID необхідно передати у дані, що підписуються.
auth.getAuthGuid()
// return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'loginByOidc (async)
Ініціює вхід через OpenID Connect — перенаправляє користувача на сторінку провайдера. Потребує налаштування параметра oidc у config.
auth.loginByOidc(options)
// return
{
success: true/false,
errorMessage: ''
}| Параметр | Тип | Опис |
|---|---|---|
| options.returnUrl | string | URI для повернення після входу |
| options.lang | string | Бажана мова інтерфейсу (BCP47, наприклад 'uk') |
| options.prompt | string | Режим автентифікації: 'login' — завжди запитувати, 'default' — на розсуд провайдера |
| options.acr_values | string | Запитані значення класу контексту автентифікації |
| options.extraQueryParams | object | Додаткові query-параметри для запиту авторизації |
loginByOidcRedirectComplite
Зберігає OIDC токен у sessionStorage після успішного редиректу. Викликається на сторінці callback.
auth.loginByOidcRedirectComplite(token)signinRedirectCallback (async)
Обробляє відповідь OIDC провайдера після редиректу на сторінку входу (callback.html).
// callback.html
auth.signinRedirectCallback()signinSilentCallback (async)
Обробляє відповідь OIDC провайдера після тихого оновлення токена (callbacksilent.html).
// callbacksilent.html
auth.signinSilentCallback()signoutRedirectCallback (async)
Обробляє відповідь OIDC провайдера після редиректу на сторінку виходу (callbacksignout.html).
// callbacksignout.html
auth.signoutRedirectCallback()getToken (async)
Повертає валідний accessToken або undefined, якщо токен відсутній. Перед поверненням автоматично оновлює токен, якщо термін дії закінчився.
const token = await auth.getToken()
// return 'eyJhbGciOiJIUzI1NiIs...' | undefinedВикористовується для перевірки наявності токена при переході на захищений роут, а також для додавання токена до запитів:
const token = await auth.getToken()
headers: {
'Authorization': `Bearer ${token}`
}Кожен виклик
getTokenскидає таймер автоматичного завершення сесії (якщо увімкненоcloseSessionAutomatically).
getTokenForServiceRequest (async)
Аналог getToken, але не скидає таймер автоматичного завершення сесії. Призначений для фонових/сервісних запитів, які не повинні вважатися активністю користувача.
const token = await auth.getTokenForServiceRequest()
// return 'eyJhbGciOiJIUzI1NiIs...' | undefinedgetUserData
Парсить accessToken і повертає інформацію про користувача або null, якщо токен відсутній.
auth.getUserData()
// return
{
id: 'userId',
login: 'userLogin',
// ...інші поля з payload токена
}logout (async)
Завершує сесію користувача. Попередньо очищає токени на клієнті та виконує запит на сервер.
При використанні OIDC — перенаправляє користувача на сторінку виходу провайдера та кидає виключення 'oidc logout redirect' для зупинки подальшого виконання коду виходу.
auth.logout(options)| Параметр | Тип | Опис |
|---|---|---|
| options.returnUrl | string | URI для повернення після виходу |
| options.lang | string | Бажана мова інтерфейсу |
| options.skipSigninSilent | boolean | Пропустити тихе оновлення перед виходом (OIDC) |
clearTokens
Видаляє всі токени з усіх сховищ (sessionStorage, cookie) та повідомляє сервер про завершення сесії.
auth.clearTokens()getDelegatedUsers (async)
Повертає список користувачів, що делегували права вказаному користувачу.
auth.getDelegatedUsers('userId')
// return
[
{
USERID: 'userId',
USERNAME: 'userName',
IsActive: true
}
]getDelegatedRights (async)
Повертає список прав, делегованих поточним користувачем іншим користувачам.
auth.getDelegatedRights()
// return
[
{
ID: 'id', // унікальний ідентифікатор
USERID: 'userId', // ID користувача
FIO: 'fio', // ПІБ користувача
USERIDSUB: 'sub', // ID заступника
FIOSUB: 'fioSub', // ПІБ заступника
DATEFROM: 'dateFrom', // дата початку
DATETO: 'dateTo', // дата закінчення
PR_DO: 'prDo', // ознака скасування
COMM: 'comm' // примітка
}
]applyDelegatedRights (async)
Застосовує права, делеговані іншим користувачем.
auth.applyDelegatedRights('userId')
// return
{
success: true/false,
errorMessage: ''
}addDelegateUser (async)
Делегує права вказаному користувачу.
auth.addDelegateUser(params)
// return
{
success: true/false,
errorMessage: ''
}params — об'єкт із параметрами делегування:
| Поле | Тип | Опис |
|---|---|---|
| userId | string | ID користувача-заступника |
| dateFrom | string | Дата початку 'YYYY-MM-DD HH:mm' |
| dateTo | string | Дата закінчення 'YYYY-MM-DD HH:mm' |
editDelegation (async)
Редагує або видаляє делеговані права.
auth.editDelegation(params)
// return
{
success: true/false,
errorMessage: ''
}params — об'єкт із параметрами:
| Поле | Тип | Опис |
|---|---|---|
| MODE | 'EDIT' | 'DELETE' | Режим операції |
| ID | string | Унікальний ідентифікатор запису (обов'язково) |
| DATEFROM | string | Дата початку (для EDIT) |
| DATETO | string | Дата закінчення (для EDIT) |
| PR_DO | string | Ознака скасування (для EDIT) |
| COMM | string | Примітка (для EDIT) |
Рекомендації
- Переконайтесь, що базовий шлях до сервера правильний і переданий у вигляді рядка.
- Для обробки результатів асинхронних методів використовуйте
async/awaitабо.then()/.catch(). - Усі публічні методи обробляють помилки та виводять відповідні повідомлення в консоль.
- При роботі з серверним API перехоплюйте помилки
statusCode = 401 (Unauthorized)для перенаправлення користувача на сторінку входу. - Якщо у застосунку використовуються делеговані права, їх можна об'єднати з даними користувача на рівні клієнта:
const user = auth.getUserData()
user.delegatedRights = await auth.getDelegatedRights() || []