fix(auth): redirect URL after signing in by SSO sucessfully (#3387)
* fix: fix T-2900 * fix: saml
This commit is contained in:
parent
88dd3dd569
commit
dc71a77d8c
@ -6,17 +6,17 @@ import { getSubAppName } from '@nocobase/sdk';
|
||||
import { Authenticator } from '@nocobase/plugin-auth/client';
|
||||
|
||||
export const SigninPage = (props: { authenticator: Authenticator }) => {
|
||||
const location = useLocation();
|
||||
|
||||
const authenticator = props.authenticator;
|
||||
const location = useLocation();
|
||||
const params = new URLSearchParams(location.search);
|
||||
const redirect = params.get('redirect');
|
||||
|
||||
const app = getSubAppName() || 'main';
|
||||
const login = async () => {
|
||||
window.location.replace(`/api/cas:login?authenticator=${authenticator.name}&__appName=${app}`);
|
||||
window.location.replace(`/api/cas:login?authenticator=${authenticator.name}&__appName=${app}&redirect=${redirect}`);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const name = params.get('authenticator');
|
||||
const error = params.get('error');
|
||||
if (name !== authenticator.name) {
|
||||
|
@ -9,7 +9,7 @@ export class SamlPlugin extends Plugin {
|
||||
const auth = this.app.pm.get(AuthPlugin);
|
||||
auth.registerType(authType, {
|
||||
components: {
|
||||
SignInForm: SigninPage,
|
||||
SignInButton: SigninPage,
|
||||
AdminSettingsForm: Options,
|
||||
},
|
||||
});
|
||||
|
@ -2,10 +2,12 @@ import { Context, Next } from '@nocobase/actions';
|
||||
import { CASAuth } from '../auth';
|
||||
|
||||
export const login = async (ctx: Context, next: Next) => {
|
||||
const { authenticator } = ctx.action.params;
|
||||
const { authenticator, redirect = '' } = ctx.action.params;
|
||||
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as CASAuth;
|
||||
const { casUrl, serviceUrl } = auth.getOptions();
|
||||
const service = encodeURIComponent(`${serviceUrl}?authenticator=${authenticator}&__appName=${ctx.app.name}`);
|
||||
const service = encodeURIComponent(
|
||||
`${serviceUrl}?authenticator=${authenticator}&__appName=${ctx.app.name}&redirect=${redirect}`,
|
||||
);
|
||||
ctx.redirect(`${casUrl}/login?service=${service}`);
|
||||
next();
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ import { AppSupervisor } from '@nocobase/server';
|
||||
import { CASAuth } from '../auth';
|
||||
|
||||
export const service = async (ctx: Context, next: Next) => {
|
||||
const { authenticator, __appName: appName } = ctx.action.params;
|
||||
const { authenticator, __appName: appName, redirect = '/admin' } = ctx.action.params;
|
||||
|
||||
let prefix = '';
|
||||
if (appName && appName !== 'main') {
|
||||
@ -16,9 +16,9 @@ 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}/admin?authenticator=${authenticator}&token=${token}`);
|
||||
ctx.redirect(`${prefix}${redirect}?authenticator=${authenticator}&token=${token}`);
|
||||
} catch (error) {
|
||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
|
||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}&redirect=${redirect}`);
|
||||
}
|
||||
return next();
|
||||
};
|
||||
|
@ -15,6 +15,8 @@ export const OIDCButton = ({ authenticator }: { authenticator: Authenticator })
|
||||
const { t } = useOidcTranslation();
|
||||
const api = useAPIClient();
|
||||
const location = useLocation();
|
||||
const params = new URLSearchParams(location.search);
|
||||
const redirect = params.get('redirect');
|
||||
|
||||
const login = async () => {
|
||||
const response = await api.request({
|
||||
@ -23,6 +25,9 @@ export const OIDCButton = ({ authenticator }: { authenticator: Authenticator })
|
||||
headers: {
|
||||
'X-Authenticator': authenticator.name,
|
||||
},
|
||||
data: {
|
||||
redirect,
|
||||
},
|
||||
});
|
||||
|
||||
const authUrl = response?.data?.data;
|
||||
@ -30,7 +35,6 @@ export const OIDCButton = ({ authenticator }: { authenticator: Authenticator })
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const name = params.get('authenticator');
|
||||
const error = params.get('error');
|
||||
if (name !== authenticator.name) {
|
||||
|
@ -4,6 +4,7 @@ import { nanoid } from 'nanoid';
|
||||
import { cookieName } from '../../constants';
|
||||
|
||||
export const getAuthUrl = async (ctx: Context, next: Next) => {
|
||||
const { redirect = '' } = ctx.action.params.values || {};
|
||||
const app = ctx.app.name;
|
||||
const auth = ctx.auth as OIDCAuth;
|
||||
const client = await auth.createOIDCClient();
|
||||
@ -16,8 +17,8 @@ export const getAuthUrl = async (ctx: Context, next: Next) => {
|
||||
ctx.body = client.authorizationUrl({
|
||||
response_type: 'code',
|
||||
scope: scope || 'openid email profile',
|
||||
redirect_uri: auth.getRedirectUri(),
|
||||
state: encodeURIComponent(`token=${token}&name=${ctx.headers['x-authenticator']}&app=${app}`),
|
||||
redirect_uri: `${auth.getRedirectUri()}`,
|
||||
state: encodeURIComponent(`token=${token}&name=${ctx.headers['x-authenticator']}&app=${app}&redirect=${redirect}`),
|
||||
});
|
||||
|
||||
return next();
|
||||
|
@ -9,6 +9,7 @@ export const redirect = async (ctx: Context, next: Next) => {
|
||||
const search = new URLSearchParams(decodeURIComponent(state));
|
||||
const authenticator = search.get('name');
|
||||
const appName = search.get('app');
|
||||
const redirect = search.get('redirect') || '/admin';
|
||||
let prefix = '';
|
||||
if (appName && appName !== 'main') {
|
||||
const appSupervisor = AppSupervisor.getInstance();
|
||||
@ -19,10 +20,10 @@ 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}/admin?authenticator=${authenticator}&token=${token}`);
|
||||
ctx.redirect(`${prefix}${redirect}?authenticator=${authenticator}&token=${token}`);
|
||||
} catch (error) {
|
||||
ctx.logger.error('OIDC auth error', { error });
|
||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
|
||||
ctx.redirect(`${prefix}/signin?redirect=${redirect}&authenticator=${authenticator}&error=${error.message}`);
|
||||
}
|
||||
await next();
|
||||
};
|
||||
|
@ -10,6 +10,8 @@ export const SAMLButton = ({ authenticator }: { authenticator: Authenticator })
|
||||
const { t } = useSamlTranslation();
|
||||
const api = useAPIClient();
|
||||
const location = useLocation();
|
||||
const params = new URLSearchParams(location.search);
|
||||
const redirect = params.get('redirect');
|
||||
|
||||
const login = async () => {
|
||||
const response = await api.request({
|
||||
@ -18,6 +20,9 @@ export const SAMLButton = ({ authenticator }: { authenticator: Authenticator })
|
||||
headers: {
|
||||
'X-Authenticator': authenticator.name,
|
||||
},
|
||||
data: {
|
||||
redirect,
|
||||
},
|
||||
});
|
||||
|
||||
const authUrl = response?.data?.data;
|
||||
@ -25,7 +30,6 @@ export const SAMLButton = ({ authenticator }: { authenticator: Authenticator })
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const name = params.get('authenticator');
|
||||
const error = params.get('error');
|
||||
if (name !== authenticator.name) {
|
||||
|
@ -3,11 +3,12 @@ import { SAML } from '@node-saml/node-saml';
|
||||
import { SAMLAuth } from '../saml-auth';
|
||||
|
||||
export const getAuthUrl = async (ctx: Context, next: Next) => {
|
||||
const { redirect = '' } = ctx.action.params.values || {};
|
||||
const auth = ctx.auth as SAMLAuth;
|
||||
const options = auth.getOptions();
|
||||
const saml = new SAML(options);
|
||||
|
||||
ctx.body = await saml.getAuthorizeUrlAsync('', '', {});
|
||||
ctx.body = await saml.getAuthorizeUrlAsync(redirect, '', {});
|
||||
|
||||
return next();
|
||||
};
|
||||
|
@ -4,6 +4,7 @@ import { AppSupervisor } from '@nocobase/server';
|
||||
|
||||
export const redirect = async (ctx: Context, next: Next) => {
|
||||
const { authenticator, __appName: appName } = ctx.action.params || {};
|
||||
const { RelayState: redirect = '/admin' } = ctx.action.params.values || {};
|
||||
let prefix = '';
|
||||
if (appName && appName !== 'main') {
|
||||
const appSupervisor = AppSupervisor.getInstance();
|
||||
@ -14,9 +15,9 @@ 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}/admin?authenticator=${authenticator}&token=${token}`);
|
||||
ctx.redirect(`${prefix}${redirect}?authenticator=${authenticator}&token=${token}`);
|
||||
} catch (error) {
|
||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}`);
|
||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}&redirect=${redirect}`);
|
||||
}
|
||||
await next();
|
||||
};
|
||||
|
@ -18,19 +18,19 @@ export class SAMLAuth extends BaseAuth {
|
||||
});
|
||||
}
|
||||
|
||||
getOptions() {
|
||||
getOptions(): SamlConfig {
|
||||
const ctx = this.ctx;
|
||||
const { ssoUrl, certificate, idpIssuer, http }: SAMLOptions = this.options?.saml || {};
|
||||
const name = this.authenticator.get('name');
|
||||
const protocol = http ? 'http' : 'https';
|
||||
return {
|
||||
callbackUrl: `${protocol}://${ctx.host}/api/saml:redirect?authenticator=${name}&app=${ctx.app.name}`,
|
||||
callbackUrl: `${protocol}://${ctx.host}/api/saml:redirect?authenticator=${name}&__appName=${ctx.app.name}`,
|
||||
entryPoint: ssoUrl,
|
||||
issuer: name,
|
||||
cert: certificate,
|
||||
idpIssuer,
|
||||
wantAssertionsSigned: false,
|
||||
} as SamlConfig;
|
||||
};
|
||||
}
|
||||
|
||||
async validate() {
|
||||
|
Loading…
Reference in New Issue
Block a user