mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-22 12:20:34 +00:00
Sso (#4235)
* feat: redirect url can be inner url (#4138) * fix: update new user sync api (#4145) * feat: post all params to backend (#4151) * pref: sso getauthurl api (#4172) * pref: sso getauthurl api * pref: sso * solve the rootorglist (#4234) --------- Co-authored-by: gggaaallleee <91131304+gggaaallleee@users.noreply.github.com>
This commit is contained in:
@@ -84,11 +84,6 @@ export type FastGPTFeConfigsType = {
|
|||||||
github?: string;
|
github?: string;
|
||||||
google?: string;
|
google?: string;
|
||||||
wechat?: string;
|
wechat?: string;
|
||||||
dingtalk?: string;
|
|
||||||
wecom?: {
|
|
||||||
corpid?: string;
|
|
||||||
agentid?: string;
|
|
||||||
};
|
|
||||||
microsoft?: {
|
microsoft?: {
|
||||||
clientId?: string;
|
clientId?: string;
|
||||||
tenantId?: string;
|
tenantId?: string;
|
||||||
|
2
packages/global/support/user/api.d.ts
vendored
2
packages/global/support/user/api.d.ts
vendored
@@ -12,8 +12,8 @@ export type PostLoginProps = {
|
|||||||
|
|
||||||
export type OauthLoginProps = {
|
export type OauthLoginProps = {
|
||||||
type: `${OAuthEnum}`;
|
type: `${OAuthEnum}`;
|
||||||
code: string;
|
|
||||||
callbackUrl: string;
|
callbackUrl: string;
|
||||||
|
props: Record<string, string>;
|
||||||
} & TrackRegisterParams;
|
} & TrackRegisterParams;
|
||||||
|
|
||||||
export type WxLoginProps = {
|
export type WxLoginProps = {
|
||||||
|
@@ -16,7 +16,5 @@ export enum OAuthEnum {
|
|||||||
google = 'google',
|
google = 'google',
|
||||||
wechat = 'wechat',
|
wechat = 'wechat',
|
||||||
microsoft = 'microsoft',
|
microsoft = 'microsoft',
|
||||||
dingtalk = 'dingtalk',
|
|
||||||
wecom = 'wecom',
|
|
||||||
sso = 'sso'
|
sso = 'sso'
|
||||||
}
|
}
|
||||||
|
@@ -94,9 +94,11 @@ function OrgTable({ Tabs }: { Tabs: React.ReactNode }) {
|
|||||||
|
|
||||||
const currentOrgs = useMemo(() => {
|
const currentOrgs = useMemo(() => {
|
||||||
if (orgs.length === 0) return [];
|
if (orgs.length === 0) return [];
|
||||||
// Auto select the first org(root org is team)
|
|
||||||
if (parentPath === '') {
|
if (parentPath === '') {
|
||||||
setParentPath(getOrgChildrenPath(orgs[0]));
|
const rootOrg = orgs.find((org) => org.path === '');
|
||||||
|
if (rootOrg) {
|
||||||
|
setParentPath(getOrgChildrenPath(rootOrg));
|
||||||
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,6 +13,7 @@ import { checkIsWecomTerminal } from '@fastgpt/global/support/user/login/constan
|
|||||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||||
import Avatar from '@fastgpt/web/components/common/Avatar';
|
import Avatar from '@fastgpt/web/components/common/Avatar';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
|
import { GET, POST } from '@/web/common/api/request';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@@ -48,8 +49,7 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
|
|||||||
{
|
{
|
||||||
label: feConfigs.sso.title || 'Unknown',
|
label: feConfigs.sso.title || 'Unknown',
|
||||||
provider: OAuthEnum.sso,
|
provider: OAuthEnum.sso,
|
||||||
icon: feConfigs.sso.icon,
|
icon: feConfigs.sso.icon
|
||||||
redirectUrl: `${feConfigs.sso.url}/login/oauth/authorize?redirect_uri=${encodeURIComponent(redirectUri)}&state=${state.current}`
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
@@ -63,16 +63,6 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
...(feConfigs?.oauth?.dingtalk
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
label: t('user:login.Dingtalk'),
|
|
||||||
provider: OAuthEnum.dingtalk,
|
|
||||||
icon: 'common/dingtalkFill',
|
|
||||||
redirectUrl: `https://login.dingtalk.com/oauth2/auth?client_id=${feConfigs?.oauth?.dingtalk}&redirect_uri=${redirectUri}&state=${state.current}&response_type=code&scope=openid&prompt=consent`
|
|
||||||
}
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
...(feConfigs?.oauth?.google
|
...(feConfigs?.oauth?.google
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
@@ -104,18 +94,6 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
...(feConfigs?.oauth?.wecom
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
label: t('login:wecom'),
|
|
||||||
provider: OAuthEnum.wecom,
|
|
||||||
icon: 'common/wecom',
|
|
||||||
redirectUrl: isWecomWorkTerminal
|
|
||||||
? `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${feConfigs?.oauth?.wecom?.corpid}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_privateinfo&agentid=${feConfigs?.oauth?.wecom?.agentid}&state=${state.current}#wechat_redirect`
|
|
||||||
: `https://login.work.weixin.qq.com/wwlogin/sso/login?login_type=CorpApp&appid=${feConfigs?.oauth?.wecom?.corpid}&agentid=${feConfigs?.oauth?.wecom?.agentid}&redirect_uri=${redirectUri}&state=${state.current}`
|
|
||||||
}
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
...(pageType !== LoginPageTypeEnum.passwordLogin
|
...(pageType !== LoginPageTypeEnum.passwordLogin
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
@@ -135,6 +113,19 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
|
|||||||
|
|
||||||
const onClickOauth = useCallback(
|
const onClickOauth = useCallback(
|
||||||
async (item: OAuthItem) => {
|
async (item: OAuthItem) => {
|
||||||
|
if (item.provider === OAuthEnum.sso) {
|
||||||
|
const redirectUrl = await POST<string>('/proApi/support/user/account/login/getAuthURL', {
|
||||||
|
redirectUri,
|
||||||
|
isWecomWorkTerminal
|
||||||
|
});
|
||||||
|
setLoginStore({
|
||||||
|
provider: item.provider as OAuthEnum,
|
||||||
|
lastRoute,
|
||||||
|
state: state.current
|
||||||
|
});
|
||||||
|
router.replace(redirectUrl, '_self');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (item.redirectUrl) {
|
if (item.redirectUrl) {
|
||||||
setLoginStore({
|
setLoginStore({
|
||||||
provider: item.provider as OAuthEnum,
|
provider: item.provider as OAuthEnum,
|
||||||
@@ -143,7 +134,6 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
|
|||||||
});
|
});
|
||||||
router.replace(item.redirectUrl, '_self');
|
router.replace(item.redirectUrl, '_self');
|
||||||
}
|
}
|
||||||
item.pageType && setPageType(item.pageType);
|
|
||||||
},
|
},
|
||||||
[lastRoute, router, setLoginStore, setPageType]
|
[lastRoute, router, setLoginStore, setPageType]
|
||||||
);
|
);
|
||||||
@@ -152,14 +142,8 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (rootLogin) return;
|
if (rootLogin) return;
|
||||||
const sso = oAuthList.find((item) => item.provider === OAuthEnum.sso);
|
const sso = oAuthList.find((item) => item.provider === OAuthEnum.sso);
|
||||||
const wecom = oAuthList.find((item) => item.provider === OAuthEnum.wecom);
|
// sso auto login
|
||||||
if (feConfigs?.sso?.autoLogin && sso) {
|
if (sso && (feConfigs?.sso?.autoLogin || isWecomWorkTerminal)) onClickOauth(sso);
|
||||||
// sso auto
|
|
||||||
onClickOauth(sso);
|
|
||||||
} else if (isWecomWorkTerminal && wecom) {
|
|
||||||
// Auto wecom login
|
|
||||||
onClickOauth(wecom);
|
|
||||||
}
|
|
||||||
}, [rootLogin, feConfigs?.sso?.autoLogin, isWecomWorkTerminal, onClickOauth]);
|
}, [rootLogin, feConfigs?.sso?.autoLogin, isWecomWorkTerminal, onClickOauth]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -19,7 +19,7 @@ const provider = () => {
|
|||||||
const { initd, loginStore, setLoginStore } = useSystemStore();
|
const { initd, loginStore, setLoginStore } = useSystemStore();
|
||||||
const { setUserInfo } = useUserStore();
|
const { setUserInfo } = useUserStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { code, state, error } = router.query as { code: string; state: string; error?: string };
|
const { state, error, ...props } = router.query as Record<string, string>;
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const loginSuccess = useCallback(
|
const loginSuccess = useCallback(
|
||||||
@@ -31,12 +31,12 @@ const provider = () => {
|
|||||||
[setUserInfo, router, loginStore?.lastRoute]
|
[setUserInfo, router, loginStore?.lastRoute]
|
||||||
);
|
);
|
||||||
|
|
||||||
const authCode = useCallback(
|
const authProps = useCallback(
|
||||||
async (code: string) => {
|
async (props: Record<string, string>) => {
|
||||||
try {
|
try {
|
||||||
const res = await oauthLogin({
|
const res = await oauthLogin({
|
||||||
type: loginStore?.provider || OAuthEnum.sso,
|
type: loginStore?.provider || OAuthEnum.sso,
|
||||||
code,
|
props,
|
||||||
callbackUrl: `${location.origin}/login/provider`,
|
callbackUrl: `${location.origin}/login/provider`,
|
||||||
inviterId: localStorage.getItem('inviterId') || undefined,
|
inviterId: localStorage.getItem('inviterId') || undefined,
|
||||||
bd_vid: sessionStorage.getItem('bd_vid') || undefined,
|
bd_vid: sessionStorage.getItem('bd_vid') || undefined,
|
||||||
@@ -86,8 +86,8 @@ const provider = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('SSO', { initd, loginStore, code, state });
|
console.log('SSO', { initd, loginStore, props, state });
|
||||||
if (!code || !initd) return;
|
if (!props || !initd) return;
|
||||||
|
|
||||||
if (isOauthLogging) return;
|
if (isOauthLogging) return;
|
||||||
|
|
||||||
@@ -107,10 +107,10 @@ const provider = () => {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
authCode(code);
|
authProps(props);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, [initd, authCode, code, error, loginStore, loginStore?.state, router, state, t, toast]);
|
}, [initd, authProps, error, loginStore, loginStore?.state, router, state, t, toast, props]);
|
||||||
|
|
||||||
return <Loading />;
|
return <Loading />;
|
||||||
};
|
};
|
||||||
|
@@ -96,7 +96,7 @@ export const getCaptchaPic = (username: string) =>
|
|||||||
captchaImage: string;
|
captchaImage: string;
|
||||||
}>('/proApi/support/user/account/captcha/getImgCaptcha', { username });
|
}>('/proApi/support/user/account/captcha/getImgCaptcha', { username });
|
||||||
|
|
||||||
export const postSyncMembers = () => POST('/proApi/support/user/team/org/sync');
|
export const postSyncMembers = () => POST('/proApi/support/user/sync');
|
||||||
|
|
||||||
export const GetSearchUserGroupOrg = (
|
export const GetSearchUserGroupOrg = (
|
||||||
searchKey: string,
|
searchKey: string,
|
||||||
|
Reference in New Issue
Block a user