diff --git a/web/berry/src/config.js b/web/berry/src/config.js index f38d16fb..14e6ffcb 100644 --- a/web/berry/src/config.js +++ b/web/berry/src/config.js @@ -23,11 +23,11 @@ const config = { version: '', wechat_login: false, wechat_qrcode: '', - oauth2: false, - oauth2_app_id: '', - oauth2_authorization_endpoint: '', - oauth2_token_endpoint: '', - oauth2_userinfo_endpoint: '', + oidc: false, + oidc_app_id: '', + oidc_authorization_endpoint: '', + oidc_token_endpoint: '', + oidc_userinfo_endpoint: '', } }; diff --git a/web/berry/src/utils/common.js b/web/berry/src/utils/common.js index a471c2cf..f9c2896c 100644 --- a/web/berry/src/utils/common.js +++ b/web/berry/src/utils/common.js @@ -98,12 +98,12 @@ export async function onLarkOAuthClicked(lark_client_id) { window.open(`https://open.feishu.cn/open-apis/authen/v1/index?redirect_uri=${redirect_uri}&app_id=${lark_client_id}&state=${state}`); } -export async function onOAuth2Clicked(auth_url, client_id, openInNewTab = false) { +export async function onOidcClicked(auth_url, client_id, openInNewTab = false) { const state = await getOAuthState(); if (!state) return; const redirect_uri = `${window.location.origin}/oauth/oidc`; const response_type = "code"; - const scope = "profile email"; + const scope = "openid profile email"; const url = `${auth_url}?client_id=${client_id}&redirect_uri=${redirect_uri}&response_type=${response_type}&scope=${scope}&state=${state}`; if (openInNewTab) { window.open(url); diff --git a/web/berry/src/views/Authentication/Auth/OidcOAuth.js b/web/berry/src/views/Authentication/Auth/OidcOAuth.js new file mode 100644 index 00000000..55d9372d --- /dev/null +++ b/web/berry/src/views/Authentication/Auth/OidcOAuth.js @@ -0,0 +1,94 @@ +import { Link, useNavigate, useSearchParams } from 'react-router-dom'; +import React, { useEffect, useState } from 'react'; +import { showError } from 'utils/common'; +import useLogin from 'hooks/useLogin'; + +// material-ui +import { useTheme } from '@mui/material/styles'; +import { Grid, Stack, Typography, useMediaQuery, CircularProgress } from '@mui/material'; + +// project imports +import AuthWrapper from '../AuthWrapper'; +import AuthCardWrapper from '../AuthCardWrapper'; +import Logo from 'ui-component/Logo'; + +// assets + +// ================================|| AUTH3 - LOGIN ||================================ // + +const OidcOAuth = () => { + const theme = useTheme(); + const matchDownSM = useMediaQuery(theme.breakpoints.down('md')); + + const [searchParams] = useSearchParams(); + const [prompt, setPrompt] = useState('处理中...'); + const { oidcLogin } = useLogin(); + + let navigate = useNavigate(); + + const sendCode = async (code, state, count) => { + const { success, message } = await oidcLogin(code, state); + if (!success) { + if (message) { + showError(message); + } + if (count === 0) { + setPrompt(`操作失败,重定向至登录界面中...`); + await new Promise((resolve) => setTimeout(resolve, 2000)); + navigate('/login'); + return; + } + count++; + setPrompt(`出现错误,第 ${count} 次重试中...`); + await new Promise((resolve) => setTimeout(resolve, 2000)); + await sendCode(code, state, count); + } + }; + + useEffect(() => { + let code = searchParams.get('code'); + let state = searchParams.get('state'); + sendCode(code, state, 0).then(); + }, []); + + return ( + + + + + + + + + + + + + + + + + + OIDC 登录 + + + + + + + + + {prompt} + + + + + + + + + + ); +}; + +export default OidcOAuth; diff --git a/web/berry/src/views/Authentication/AuthForms/AuthLogin.js b/web/berry/src/views/Authentication/AuthForms/AuthLogin.js index 582fdfbe..7e4abc1c 100644 --- a/web/berry/src/views/Authentication/AuthForms/AuthLogin.js +++ b/web/berry/src/views/Authentication/AuthForms/AuthLogin.js @@ -36,7 +36,8 @@ import VisibilityOff from '@mui/icons-material/VisibilityOff'; import Github from 'assets/images/icons/github.svg'; import Wechat from 'assets/images/icons/wechat.svg'; import Lark from 'assets/images/icons/lark.svg'; -import { onGitHubOAuthClicked, onLarkOAuthClicked, onOAuth2Clicked } from 'utils/common'; +import OIDC from 'assets/images/icons/oidc.svg'; +import { onGitHubOAuthClicked, onLarkOAuthClicked, onOidcClicked } from 'utils/common'; // ============================|| FIREBASE - LOGIN ||============================ // @@ -50,7 +51,7 @@ const LoginForm = ({ ...others }) => { // const [checked, setChecked] = useState(true); let tripartiteLogin = false; - if (siteInfo.github_oauth || siteInfo.wechat_login || siteInfo.lark_client_id || siteInfo.oauth2) { + if (siteInfo.github_oauth || siteInfo.wechat_login || siteInfo.lark_client_id || siteInfo.oidc) { tripartiteLogin = true; } @@ -145,13 +146,13 @@ const LoginForm = ({ ...others }) => { )} - {siteInfo.oauth2 && ( + {siteInfo.oidc && ( diff --git a/web/berry/src/views/Profile/index.js b/web/berry/src/views/Profile/index.js index 4705d8af..721ead7b 100644 --- a/web/berry/src/views/Profile/index.js +++ b/web/berry/src/views/Profile/index.js @@ -20,7 +20,7 @@ import SubCard from 'ui-component/cards/SubCard'; import { IconBrandWechat, IconBrandGithub, IconMail } from '@tabler/icons-react'; import Label from 'ui-component/Label'; import { API } from 'utils/api'; -import { showError, showSuccess } from 'utils/common'; +import { onOidcClicked, showError, showSuccess } from 'utils/common'; import { onGitHubOAuthClicked, onLarkOAuthClicked, copy } from 'utils/common'; import * as Yup from 'yup'; import WechatModal from 'views/Authentication/AuthForms/WechatModal'; @@ -28,6 +28,7 @@ import { useSelector } from 'react-redux'; import EmailModal from './component/EmailModal'; import Turnstile from 'react-turnstile'; import { ReactComponent as Lark } from 'assets/images/icons/lark.svg'; +import { ReactComponent as OIDC } from 'assets/images/icons/oidc.svg'; const validationSchema = Yup.object().shape({ username: Yup.string().required('用户名 不能为空').min(3, '用户名 不能小于 3 个字符'), @@ -123,6 +124,15 @@ export default function Profile() { loadUser().then(); }, [status]); + function getOidcId(){ + if (!inputs.oidc_id) return ''; + let oidc_id = inputs.oidc_id; + if (inputs.oidc_id.length > 8) { + oidc_id = inputs.oidc_id.slice(0, 6) + '...' + inputs.oidc_id.slice(-6); + } + return oidc_id; + } + return ( <> @@ -141,6 +151,9 @@ export default function Profile() { + @@ -216,6 +229,13 @@ export default function Profile() { )} + {status.oidc && !inputs.oidc_id && ( + + + + )}