@sberid/js-sdk
Version:
Javascript SDK для партнеров Сбер ID, упрощающая подключение SberbankID на сайте.
175 lines (152 loc) • 6.15 kB
text/typescript
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;
}
}