import qs from 'qs' import shortid from 'shortid' import React, { FC, useEffect } from 'react' import { Button, Avatar, Space, Tooltip, message } from 'antd' import { isWechatBrowser, popupCenter } from '../../../../utils' import { useGuardContext } from '../../../../context/global/context' import { APP_MFA_CODE, OTP_MFA_CODE } from '../../constants' import { Lang, Protocol, SocialAndIdpLoginProps } from '../../types' import { OIDCConnectionConfig, ICasConnectionConfig, ISamlConnectionConfig, IAzureAdConnectionConfig, IOAuthConnectionConfig, } from '../../api' import { requestClient } from '../../api/http' import './style.less' import { IconFont } from '../../IconFont' import { useScreenSize } from '../../hooks/useScreenSize' import { SocialConnectionProvider } from 'approw-js-sdk' import { useTranslation } from 'react-i18next' import { i18n } from '../../locales' export const SocialAndIdpLogin: FC = ({ onFail = () => {}, onSuccess = () => {}, }) => { const { state: { config, userPoolId, appId, authClient }, } = useGuardContext() const { t } = useTranslation() const noForm = !config.loginMethods?.length const [screenSize] = useScreenSize() useEffect(() => { const onMessage = (evt: MessageEvent) => { // TODO: event.origin是指发送的消息源,一定要进行验证!!! const { code, message: errMsg, data, event } = evt.data const { source, eventType } = event || {} // 社会化登录是用 approw-js-sdk 实现的,不用再在这里回调了 if (source === 'approw' && eventType === 'socialLogin') { return } try { const parsedMsg = JSON.parse(errMsg) const { code: approwCode } = parsedMsg if ([OTP_MFA_CODE, APP_MFA_CODE].includes(approwCode)) { onFail(parsedMsg) return } } catch (e) { // do nothing... } if (code !== undefined) { if (code === 200) { localStorage.setItem('_approw_token', data?.token) onSuccess(data) } else { message.error(errMsg) } } } window.addEventListener('message', onMessage) return () => { window.removeEventListener('message', onMessage) } }, [onFail, onSuccess]) const idpButtons = config.enterpriseConnectionObjs.map((i) => { if (i.protocol === Protocol.OIDC) { const configItem = i.config as OIDCConnectionConfig const state = shortid.generate() const query = qs.stringify({ client_id: configItem.clientId, redirect_uri: configItem.redirectUri, scope: configItem.scopes, response_type: configItem.responseType, state, nonce: shortid.generate(), }) const url = `${configItem.authorizationEdpoint}?${query}` return ( ) } else if (i.protocol === Protocol.SAML) { const config = i.config as ISamlConnectionConfig return ( ) } else if (i.protocol === Protocol.CAS) { const config = i.config as ICasConnectionConfig return ( ) } else if (i.protocol === Protocol.OAUTH) { const config = i.config as IOAuthConnectionConfig return ( ) } else if (i.protocol === Protocol.AZURE_AD) { const configItem = i.config as IAzureAdConnectionConfig return ( ) } else { return null } }) const socialLoginButtons = config.socialConnectionObjs .filter((item) => isWechatBrowser() ? item.provider === SocialConnectionProvider.WECHATMP : item.provider !== SocialConnectionProvider.WECHATMP ) .map((item) => { const iconType = `approw-${item.provider.replace(/:/g, '-')}` const authorization_params: Record = {} if (item.provider === SocialConnectionProvider.BAIDU) { authorization_params.display = screenSize } const onLogin = () => { authClient.social.authorize(item.provider, { onSuccess(user) { onSuccess(user) }, onError(code, msg) { try { const parsedMsg = JSON.parse(msg) const { code: approwCode } = parsedMsg if ([OTP_MFA_CODE, APP_MFA_CODE].includes(approwCode)) { onFail(parsedMsg) return } } catch (e) { // do nothing... } message.error(msg) }, authorization_params, }) } return noForm ? ( ) : (
) }) const idp = config.enterpriseConnectionObjs.length > 0 ? ( <> {!noForm &&
OR
} {idpButtons} ) : null const socialLogin = socialLoginButtons.length > 0 && noForm ? ( {socialLoginButtons} ) : ( socialLoginButtons.length > 0 && ( <>
{t('login.thridAccLogin')}
{socialLoginButtons}
) ) return ( <> {!noForm && (
)} {idp} {socialLogin} ) }