feat(auth): add global auth token provider (#2824)
This commit is contained in:
parent
2d593175b9
commit
6f09d7ad06
@ -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>
|
||||||
|
);
|
||||||
|
};
|
@ -1,41 +1,19 @@
|
|||||||
import {
|
import { useAPIClient } from '@nocobase/client';
|
||||||
OptionsComponentProvider,
|
import React, { useEffect } from 'react';
|
||||||
SettingsCenterProvider,
|
import { useLocation } from 'react-router-dom';
|
||||||
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 AuthProvider: FC = (props) => {
|
export const AuthProvider: React.FC = (props) => {
|
||||||
const { t } = useAuthTranslation();
|
const location = useLocation();
|
||||||
return (
|
const api = useAPIClient();
|
||||||
<SettingsCenterProvider
|
|
||||||
settings={{
|
useEffect(() => {
|
||||||
auth: {
|
const params = new URLSearchParams(location.search);
|
||||||
title: t('Authentication'),
|
const authenticator = params.get('authenticator');
|
||||||
icon: 'LoginOutlined',
|
const token = params.get('token');
|
||||||
tabs: {
|
if (token) {
|
||||||
authenticators: {
|
api.auth.setToken(token);
|
||||||
title: t('Authenticators'),
|
api.auth.setAuthenticator(authenticator);
|
||||||
component: () => <Authenticator />,
|
}
|
||||||
},
|
});
|
||||||
},
|
return <>{props.children}</>;
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<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>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { Plugin } from '@nocobase/client';
|
import { Plugin } from '@nocobase/client';
|
||||||
|
import { AuthPluginProvider } from './AuthPluginProvider';
|
||||||
import { AuthProvider } from './AuthProvider';
|
import { AuthProvider } from './AuthProvider';
|
||||||
|
|
||||||
export class AuthPlugin extends Plugin {
|
export class AuthPlugin extends Plugin {
|
||||||
async load() {
|
async load() {
|
||||||
this.app.use(AuthProvider);
|
this.app.providers.unshift([AuthProvider, {}]);
|
||||||
|
this.app.use(AuthPluginProvider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Authenticator, useAPIClient, useRedirect, useCurrentUserContext } from '@nocobase/client';
|
import { Authenticator, useRedirect } from '@nocobase/client';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { LoginOutlined } from '@ant-design/icons';
|
import { LoginOutlined } from '@ant-design/icons';
|
||||||
import { Button, Space, message } from 'antd';
|
import { Button, Space, message } from 'antd';
|
||||||
@ -6,10 +6,8 @@ import { useLocation } from 'react-router-dom';
|
|||||||
import { getSubAppName } from '@nocobase/sdk';
|
import { getSubAppName } from '@nocobase/sdk';
|
||||||
|
|
||||||
export const SigninPage = (props: { authenticator: Authenticator }) => {
|
export const SigninPage = (props: { authenticator: Authenticator }) => {
|
||||||
const api = useAPIClient();
|
|
||||||
const redirect = useRedirect();
|
const redirect = useRedirect();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { refreshAsync: refresh } = useCurrentUserContext();
|
|
||||||
|
|
||||||
const authenticator = props.authenticator;
|
const authenticator = props.authenticator;
|
||||||
|
|
||||||
@ -21,7 +19,6 @@ export const SigninPage = (props: { authenticator: Authenticator }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
const token = params.get('token');
|
|
||||||
const name = params.get('authenticator');
|
const name = params.get('authenticator');
|
||||||
const error = params.get('error');
|
const error = params.get('error');
|
||||||
if (name !== authenticator.name) {
|
if (name !== authenticator.name) {
|
||||||
@ -31,14 +28,6 @@ export const SigninPage = (props: { authenticator: Authenticator }) => {
|
|||||||
message.error(error);
|
message.error(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (token) {
|
|
||||||
api.auth.setToken(token);
|
|
||||||
api.auth.setAuthenticator(name);
|
|
||||||
refresh()
|
|
||||||
.then(() => redirect())
|
|
||||||
.catch((err) => console.log(err));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -16,7 +16,7 @@ export const service = async (ctx: Context, next: Next) => {
|
|||||||
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as CASAuth;
|
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as CASAuth;
|
||||||
try {
|
try {
|
||||||
const { token } = await auth.signIn();
|
const { token } = await auth.signIn();
|
||||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&token=${token}`);
|
ctx.redirect(`${prefix}/admin?authenticator=${authenticator}&token=${token}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
|
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { LoginOutlined } from '@ant-design/icons';
|
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 { Button, Space, message } from 'antd';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useOidcTranslation } from './locale';
|
import { useOidcTranslation } from './locale';
|
||||||
@ -13,9 +13,7 @@ export interface OIDCProvider {
|
|||||||
export const OIDCButton = ({ authenticator }: { authenticator: Authenticator }) => {
|
export const OIDCButton = ({ authenticator }: { authenticator: Authenticator }) => {
|
||||||
const { t } = useOidcTranslation();
|
const { t } = useOidcTranslation();
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const redirect = useRedirect();
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { refreshAsync: refresh } = useCurrentUserContext();
|
|
||||||
|
|
||||||
const login = async () => {
|
const login = async () => {
|
||||||
const response = await api.request({
|
const response = await api.request({
|
||||||
@ -32,7 +30,6 @@ export const OIDCButton = ({ authenticator }: { authenticator: Authenticator })
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
const token = params.get('token');
|
|
||||||
const name = params.get('authenticator');
|
const name = params.get('authenticator');
|
||||||
const error = params.get('error');
|
const error = params.get('error');
|
||||||
if (name !== authenticator.name) {
|
if (name !== authenticator.name) {
|
||||||
@ -42,14 +39,6 @@ export const OIDCButton = ({ authenticator }: { authenticator: Authenticator })
|
|||||||
message.error(t(error));
|
message.error(t(error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (token) {
|
|
||||||
api.auth.setToken(token);
|
|
||||||
api.auth.setAuthenticator(name);
|
|
||||||
refresh()
|
|
||||||
.then(() => redirect())
|
|
||||||
.catch((err) => console.log(err));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -19,7 +19,7 @@ export const redirect = async (ctx: Context, next: Next) => {
|
|||||||
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as OIDCAuth;
|
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as OIDCAuth;
|
||||||
try {
|
try {
|
||||||
const { token } = await auth.signIn();
|
const { token } = await auth.signIn();
|
||||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&token=${token}`);
|
ctx.redirect(`${prefix}/admin?authenticator=${authenticator}&token=${token}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
|
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { LoginOutlined } from '@ant-design/icons';
|
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 { Button, Space, message } from 'antd';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useSamlTranslation } from './locale';
|
import { useSamlTranslation } from './locale';
|
||||||
@ -8,9 +8,7 @@ import { useLocation } from 'react-router-dom';
|
|||||||
export const SAMLButton = ({ authenticator }: { authenticator: Authenticator }) => {
|
export const SAMLButton = ({ authenticator }: { authenticator: Authenticator }) => {
|
||||||
const { t } = useSamlTranslation();
|
const { t } = useSamlTranslation();
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const redirect = useRedirect();
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { refreshAsync: refresh } = useCurrentUserContext();
|
|
||||||
|
|
||||||
const login = async () => {
|
const login = async () => {
|
||||||
const response = await api.request({
|
const response = await api.request({
|
||||||
@ -27,7 +25,6 @@ export const SAMLButton = ({ authenticator }: { authenticator: Authenticator })
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
const token = params.get('token');
|
|
||||||
const name = params.get('authenticator');
|
const name = params.get('authenticator');
|
||||||
const error = params.get('error');
|
const error = params.get('error');
|
||||||
if (name !== authenticator.name) {
|
if (name !== authenticator.name) {
|
||||||
@ -37,14 +34,6 @@ export const SAMLButton = ({ authenticator }: { authenticator: Authenticator })
|
|||||||
message.error(error);
|
message.error(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (token) {
|
|
||||||
api.auth.setToken(token);
|
|
||||||
api.auth.setAuthenticator(name);
|
|
||||||
refresh()
|
|
||||||
.then(() => redirect())
|
|
||||||
.catch((err) => console.log(err));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -14,7 +14,7 @@ export const redirect = async (ctx: Context, next: Next) => {
|
|||||||
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as SAMLAuth;
|
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as SAMLAuth;
|
||||||
try {
|
try {
|
||||||
const { token } = await auth.signIn();
|
const { token } = await auth.signIn();
|
||||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&token=${token}`);
|
ctx.redirect(`${prefix}/admin?authenticator=${authenticator}&token=${token}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
|
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user