UNPKG

@sberid/js-sdk

Version:

Javascript SDK для партнеров Сбер ID, упрощающая подключение SberbankID на сайте.

175 lines (152 loc) 6.15 kB
import {BASE_URL} from '../constants/common'; import {defaultFastLoginConfig} from './constants'; import {OidcParams} from '../interfaces/common'; import {buildUrl, log} from '../utils/common'; import {AbstractFastLogin, FastAuthorizationResponse, Message, FastLoginConfig} from './interfaces'; import {createIframe, listenWindowMessages, postMessageToIframe} from './utils'; import {ERROR_MESSAGES} from '../sberid-sdk/constants'; import {SberidSDKProps} from '../sberid-sdk'; export class FastLogin implements AbstractFastLogin { isFastLoginIframeRegistered = false; isFastLoginDataFetched = false; fastLoginIframe!: HTMLIFrameElement; config: FastLoginConfig; iFrameName: string; removeLoadDataListener(): void {} constructor(config: SberidSDKProps) { this.iFrameName = 'sberid-iframe'; this.isFastLoginIframeRegistered = false; this.isFastLoginDataFetched = false; this.config = { ...defaultFastLoginConfig, ...config.fastLogin, debug: config.debug, baseUrl: config.baseUrl || BASE_URL, oidcParams: config.oidc, }; } async authorization(oidcParams?: OidcParams): Promise<FastAuthorizationResponse> { const params = oidcParams || this.config.oidcParams; if (!params) { return new Promise((_, reject) => { reject({ code: 'error', error: 'invalid_request', description: ERROR_MESSAGES['invalid_request'], }); }); } const url = this.buildUrl(params); return await this.createIFrame(url).catch((err) => err); } buildUrl(oidcParams: OidcParams): string { const params: OidcParams = { prompt: 'none', ...oidcParams, }; return buildUrl(`${this.config.baseUrl}/CSAFront/oidc/authorizelow.do`, params); } async createIFrame(url: string): Promise<FastAuthorizationResponse> { this.fastLoginIframe = createIframe( url, this.iFrameName, (e) => { this.onFastLoginIframeCreateSuccess(e); }, () => { this.destroyFastLogin(); throw { success: false, error: { code: 'error', error: 'iframe_error', description: 'Ошибка при создании iframe', }, }; }, ); document.body.append(this.fastLoginIframe); return new Promise((resolve, reject) => { const timeoutID = setTimeout(() => { this.destroyFastLogin(); reject({ success: false, error: { type: 'timeout', description: 'Ошибка при создании iframe', }, }); }, this.config.timeout); const removeRegisterIframeListener = listenWindowMessages((v: Message) => { if (v.type === 'iframe is registered') { clearTimeout(timeoutID); this.isFastLoginIframeRegistered = true; this.loadFastLoginData() .then((data) => { resolve(data); }) .catch((data) => { reject(data); }) .finally(() => { this.destroyFastLogin(); }); removeRegisterIframeListener(); } }); }); } onFastLoginIframeCreateSuccess(r?: Event): void { if (this.config.debug) { log(['Iframe для быстрого входа создан', r]); } } async loadFastLoginData(): Promise<FastAuthorizationResponse> { if (this.isFastLoginIframeRegistered) { await this.fetchFastLoginData(); } return new Promise((resolve, reject) => { this.removeLoadDataListener = listenWindowMessages(async (v: Message) => { switch (v.type) { case 'iframe is registered': await this.fetchFastLoginData(); break; case 'success': if (this.config.debug) { log(['Успешно получены данные при быстром входе', v.data], 'success'); } resolve(v.data); break; case 'error': if (this.config.debug) { log(['Ошибка получения данных при быстром входе', v.data], 'error'); } reject(v.data); break; default: break; } }); }); } async fetchFastLoginData(): Promise<void> { if (this.isFastLoginDataFetched || !this.fastLoginIframe) { return; } postMessageToIframe({type: 'fetch data'}, this.fastLoginIframe?.contentWindow); this.isFastLoginDataFetched = true; } destroyFastLogin(): void { if (this.config.debug) { log(['Iframe для быстрого входа удален']); } if (this.fastLoginIframe) { this.fastLoginIframe.remove(); } if (this.removeLoadDataListener) { this.removeLoadDataListener(); } this.isFastLoginIframeRegistered = false; this.isFastLoginDataFetched = false; } }