# [PAXUM-6983](https://jira.paydek.com/browse/PAXUM-6983) Push to login ## BRD: Currently, we have a functionality where user can require 2fa in order to login We need to introduce similar functionality via PUSH notification User can select Push Verifiection to login If selected, when user logs in , after entering username / password they receive a push notification on all of their linked devices. Notification should contain browser and location of login ie: Mac OS / Chome 98 from Orinda, CA (same info we display on login history) They can approve or reject the login If approved they can proceed , rejected should return to login screen ## Functional requirements: * Пользователь должен иметь возможность включить двух факторную авторизацию и выбирать метод авторизации **OTP** или **Подтверждение с одобренного устройства** *(Далее при Подтверждение с одобренного устройства)* * При логине пользователь должен увидеть на СПА экран(сообщение) о том, что ему необходимо подтвердить авторизацию с мобильного устройства * В мобильное устройство приходит пуш-нотификация, и имеется возможность на неё нажать, после чего открывается приложение с экраном(уведомлением) о том, что кто-то пытается авторизоваться с `такого-то` браузера и двумя кнопками `Подтвердить` и `Отклонить` * Результат в реальном времени отображается в СПА приложении. Если авторизацию отклонили, то СПА должно вернуться на форму авторизации, если подтвердили, то СПА должно перейти в личный кабинет ## Suggested flow for Authorization: ```sequence Пользователь->СПА: 1. Ввод кредов СПА->Бек: 2. Авторизация в ТС Бек->СПА: 3. Токен СПА->Бек: 4. Другие запросы Бек->СПА: 5. 403 ошибка СПА->Бек: 6. Инициация Пуша Бек->Мобилка: 7. Пуш Бек->СПА: 8. Временный канал СПА->Центрифуга: 9. Авторизация Мобилка->Пользователь: 10. Оповещение Пользователь->Мобилка: 11. Принимает решение Мобилка->Бек: 12. Решение Бек->Центрифуга: 13. Результат Центрифуга->СПА: 14. Результат СПА->Пользователь: 15. Вход ``` 1. Пользователь вводит данные для авторизации 2. СПА авторизуется в Токен сервисе 3. Токен сервис возращает Токен с `2faMode = false` 4. СПА пытается запросить другие методы для которых требуется 2fa 5. Бэк возвращает 403 `#ForbiddenDto` 6. СПА инициирует отправку пуша. Запрос №1 7. Бек отправляет пуш `#PushPayloadDto` на мобилку 8. Бек возвращает СПА данные #TemporaryChannelDto для временного канала в Центрифуге 9. СПА авторизуется в Центрифуге во временном канале 10. Мобилка оповещает пользователя о Авторизации 11. Пользователь принимает решение и нажимает кнопку Авторизовать/отклонить 12. Мобилка отправляет решение на Бек. Запрос №2 13. Бек отправляет результат в центрифугу #AuthResultDto 14. Центрифуга отправляет результат СПА в приватном канале #AuthResultDto 15. Eсли приходит `result=false`, то необходимо вернуть пользователя на экран авторизации, в случае если `result=true`, то в свойстве придут `credentials`, с которыми можно авторизовывать пользователя в системе ## Routes ##### 1. Инициация пуша ``` POST /v4/push-api/auth-verification ``` :::spoiler Подсказка Тело запроса пустое, главное отправить с токеном, который выписал Токен сервис ::: ##### 2. Подтверждение/отклонение авторизации с мобильного устройства: ``` POST /v4/confirmation-by-device/auth/{uuid}/confirm #AuthConfiramtionDto ``` :::spoiler Подсказка **Uuid** в теле url берётся из #PushPayloadDto ::: ## DTOs #### ForbiddenDto: ```json= { message: "Подтвердите авторизацию со следующего устройтсва", type: "push", // or OTP } ``` #### PushPayloadDto: ```json= { // Payload pushType: "AuthVerification", authUuid: "uuid попытки логина", exp: 1615381490, payload : { "ip" : "192.168.0.1", "country" : "Russia", "city" : "Moscow", "browser" : "Chrome", "version": "44.4", "platform": "Mac OS X" } } ``` #### TemporaryChannelDto: ```json= { channel: "auth#1a53db9d-80df-423d-b8fe-32c921645b8f", token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJmMDhmYzc5OS04NjYxLTRhMTQtOTdiYy00ZTkxNGUyODUzODIiLCJleHAiOjE2MTU4MjgyNTF9.J4i9B4X4pmapi5sh2bPbUWqNbWma3ziM86X2z4PpW88", devices: ["Iphone (Anton)"] } ``` :::info JWT-токен для авторизации в приватном канале `auth` в Центрифуге ::: #### AuthConfiramtionDto ```json= { result: true // Confirmed or declined } ``` #### AuthResultDto ```json= { result: false, // true ?credentials: #CredentialsDto } ``` #### CredentialsDto ```json= { "refresh": "b72b377d0cd5e082551761d6c725cd0a", "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTU1NTc5NzAsImV4cCI6MTYxNTU1ODE1MCwidWlkIjoxMTA4MzM0MTEsImxvZ2luV2l0aDJmYSI6ZmFsc2V9.IMigZmtt8WLUmb9ykprAD5Pf7mMWsoSnITDenGU8H4M", "refreshTtl": 1800, "accessTtl": 180 } ``` ## Links * https://centrifugo.ashtein.ru/ - ``` const centrifuge = new Centrifuge("wss://centrifugo.ashtein.ru/connection/websocket") ``` * For js `npm install centrifuge` * [Документация Центрифуги JS](https://centrifugal.github.io/centrifugo/server/client_api/)