feat(auth): add global auth token provider (#2824)

This commit is contained in:
YANG QIA 2023-10-13 05:12:26 -05:00 committed by GitHub
parent 2d593175b9
commit 6f09d7ad06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 67 additions and 79 deletions

View File

@ -0,0 +1,41 @@
import {
OptionsComponentProvider,
SettingsCenterProvider,
SigninPageProvider,
SignupPageProvider,
} from '@nocobase/client';
import React, { FC } from 'react';
import { Authenticator } from './settings/Authenticator';
import SigninPage from './basic/SigninPage';
import { presetAuthType } from '../preset';
import SignupPage from './basic/SignupPage';
import { useAuthTranslation } from './locale';
import { Options } from './basic/Options';
export const AuthPluginProvider: FC = (props) => {
const { t } = useAuthTranslation();
return (
<SettingsCenterProvider
settings={{
auth: {
title: t('Authentication'),
icon: 'LoginOutlined',
tabs: {
authenticators: {
title: t('Authenticators'),
component: () => <Authenticator />,
},
},
},
}}
>
<OptionsComponentProvider authType={presetAuthType} component={Options}>
<SigninPageProvider authType={presetAuthType} tabTitle={t('Sign in via password')} component={SigninPage}>
<SignupPageProvider authType={presetAuthType} component={SignupPage}>
{props.children}
</SignupPageProvider>
</SigninPageProvider>
</OptionsComponentProvider>
</SettingsCenterProvider>
);
};

View File

@ -1,41 +1,19 @@
import {
OptionsComponentProvider,
SettingsCenterProvider,
SigninPageProvider,
SignupPageProvider,
} from '@nocobase/client';
import React, { FC } from 'react';
import { Authenticator } from './settings/Authenticator';
import SigninPage from './basic/SigninPage';
import { presetAuthType } from '../preset';
import SignupPage from './basic/SignupPage';
import { useAuthTranslation } from './locale';
import { Options } from './basic/Options';
import { useAPIClient } from '@nocobase/client';
import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
export const AuthProvider: FC = (props) => {
const { t } = useAuthTranslation();
return (
<SettingsCenterProvider
settings={{
auth: {
title: t('Authentication'),
icon: 'LoginOutlined',
tabs: {
authenticators: {
title: t('Authenticators'),
component: () => <Authenticator />,
},
},
},
}}
>
<OptionsComponentProvider authType={presetAuthType} component={Options}>
<SigninPageProvider authType={presetAuthType} tabTitle={t('Sign in via password')} component={SigninPage}>
<SignupPageProvider authType={presetAuthType} component={SignupPage}>
{props.children}
</SignupPageProvider>
</SigninPageProvider>
</OptionsComponentProvider>
</SettingsCenterProvider>
);
export const AuthProvider: React.FC = (props) => {
const location = useLocation();
const api = useAPIClient();
useEffect(() => {
const params = new URLSearchParams(location.search);
const authenticator = params.get('authenticator');
const token = params.get('token');
if (token) {
api.auth.setToken(token);
api.auth.setAuthenticator(authenticator);
}
});
return <>{props.children}</>;
};

View File

@ -1,9 +1,11 @@
import { Plugin } from '@nocobase/client';
import { AuthPluginProvider } from './AuthPluginProvider';
import { AuthProvider } from './AuthProvider';
export class AuthPlugin extends Plugin {
async load() {
this.app.use(AuthProvider);
this.app.providers.unshift([AuthProvider, {}]);
this.app.use(AuthPluginProvider);
}
}

View File

@ -1,4 +1,4 @@
import { Authenticator, useAPIClient, useRedirect, useCurrentUserContext } from '@nocobase/client';
import { Authenticator, useRedirect } from '@nocobase/client';
import React, { useEffect } from 'react';
import { LoginOutlined } from '@ant-design/icons';
import { Button, Space, message } from 'antd';
@ -6,10 +6,8 @@ import { useLocation } from 'react-router-dom';
import { getSubAppName } from '@nocobase/sdk';
export const SigninPage = (props: { authenticator: Authenticator }) => {
const api = useAPIClient();
const redirect = useRedirect();
const location = useLocation();
const { refreshAsync: refresh } = useCurrentUserContext();
const authenticator = props.authenticator;
@ -21,7 +19,6 @@ export const SigninPage = (props: { authenticator: Authenticator }) => {
useEffect(() => {
const params = new URLSearchParams(location.search);
const token = params.get('token');
const name = params.get('authenticator');
const error = params.get('error');
if (name !== authenticator.name) {
@ -31,14 +28,6 @@ export const SigninPage = (props: { authenticator: Authenticator }) => {
message.error(error);
return;
}
if (token) {
api.auth.setToken(token);
api.auth.setAuthenticator(name);
refresh()
.then(() => redirect())
.catch((err) => console.log(err));
return;
}
});
return (

View File

@ -16,7 +16,7 @@ export const service = async (ctx: Context, next: Next) => {
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as CASAuth;
try {
const { token } = await auth.signIn();
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&token=${token}`);
ctx.redirect(`${prefix}/admin?authenticator=${authenticator}&token=${token}`);
} catch (error) {
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
}

View File

@ -1,5 +1,5 @@
import { LoginOutlined } from '@ant-design/icons';
import { Authenticator, css, useAPIClient, useCurrentUserContext, useRedirect } from '@nocobase/client';
import { Authenticator, css, useAPIClient } from '@nocobase/client';
import { Button, Space, message } from 'antd';
import React, { useEffect } from 'react';
import { useOidcTranslation } from './locale';
@ -13,9 +13,7 @@ export interface OIDCProvider {
export const OIDCButton = ({ authenticator }: { authenticator: Authenticator }) => {
const { t } = useOidcTranslation();
const api = useAPIClient();
const redirect = useRedirect();
const location = useLocation();
const { refreshAsync: refresh } = useCurrentUserContext();
const login = async () => {
const response = await api.request({
@ -32,7 +30,6 @@ export const OIDCButton = ({ authenticator }: { authenticator: Authenticator })
useEffect(() => {
const params = new URLSearchParams(location.search);
const token = params.get('token');
const name = params.get('authenticator');
const error = params.get('error');
if (name !== authenticator.name) {
@ -42,14 +39,6 @@ export const OIDCButton = ({ authenticator }: { authenticator: Authenticator })
message.error(t(error));
return;
}
if (token) {
api.auth.setToken(token);
api.auth.setAuthenticator(name);
refresh()
.then(() => redirect())
.catch((err) => console.log(err));
return;
}
});
return (

View File

@ -19,7 +19,7 @@ export const redirect = async (ctx: Context, next: Next) => {
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as OIDCAuth;
try {
const { token } = await auth.signIn();
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&token=${token}`);
ctx.redirect(`${prefix}/admin?authenticator=${authenticator}&token=${token}`);
} catch (error) {
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
}

View File

@ -1,5 +1,5 @@
import { LoginOutlined } from '@ant-design/icons';
import { Authenticator, css, useAPIClient, useCurrentUserContext, useRedirect } from '@nocobase/client';
import { Authenticator, css, useAPIClient } from '@nocobase/client';
import { Button, Space, message } from 'antd';
import React, { useEffect } from 'react';
import { useSamlTranslation } from './locale';
@ -8,9 +8,7 @@ import { useLocation } from 'react-router-dom';
export const SAMLButton = ({ authenticator }: { authenticator: Authenticator }) => {
const { t } = useSamlTranslation();
const api = useAPIClient();
const redirect = useRedirect();
const location = useLocation();
const { refreshAsync: refresh } = useCurrentUserContext();
const login = async () => {
const response = await api.request({
@ -27,7 +25,6 @@ export const SAMLButton = ({ authenticator }: { authenticator: Authenticator })
useEffect(() => {
const params = new URLSearchParams(location.search);
const token = params.get('token');
const name = params.get('authenticator');
const error = params.get('error');
if (name !== authenticator.name) {
@ -37,14 +34,6 @@ export const SAMLButton = ({ authenticator }: { authenticator: Authenticator })
message.error(error);
return;
}
if (token) {
api.auth.setToken(token);
api.auth.setAuthenticator(name);
refresh()
.then(() => redirect())
.catch((err) => console.log(err));
return;
}
});
return (

View File

@ -14,7 +14,7 @@ export const redirect = async (ctx: Context, next: Next) => {
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as SAMLAuth;
try {
const { token } = await auth.signIn();
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&token=${token}`);
ctx.redirect(`${prefix}/admin?authenticator=${authenticator}&token=${token}`);
} catch (error) {
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
}