mirror of
https://github.com/logto-io/logto.git
synced 2024-12-23 20:33:16 -05:00
Merge pull request #1810 from logto-io/gao-log-3981-core-check-sign-in-mode-and-guard
feat(core): guard session with sign-in mode
This commit is contained in:
commit
a2043a6804
3 changed files with 53 additions and 1 deletions
|
@ -10,11 +10,15 @@ import { assignInteractionResults, saveUserFirstConsentedAppId } from '@/lib/ses
|
|||
import assertThat from '@/utils/assert-that';
|
||||
|
||||
import { AnonymousRouter } from '../types';
|
||||
import koaGuardSessionAction from './middleware/koa-guard-session-action';
|
||||
import passwordlessRoutes from './passwordless';
|
||||
import socialRoutes from './social';
|
||||
import usernamePasswordRoutes from './username-password';
|
||||
|
||||
export default function sessionRoutes<T extends AnonymousRouter>(router: T, provider: Provider) {
|
||||
router.use('/session/sign-in', koaGuardSessionAction(provider, 'sign-in'));
|
||||
router.use('/session/register', koaGuardSessionAction(provider, 'register'));
|
||||
|
||||
router.post('/session', async (ctx, next) => {
|
||||
const {
|
||||
prompt: { name },
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import { SignInMode } from '@logto/schemas';
|
||||
import { adminConsoleApplicationId } from '@logto/schemas/lib/seeds';
|
||||
import { MiddlewareType } from 'koa';
|
||||
import { Provider, errors } from 'oidc-provider';
|
||||
|
||||
import RequestError from '@/errors/RequestError';
|
||||
import { findDefaultSignInExperience } from '@/queries/sign-in-experience';
|
||||
import assertThat from '@/utils/assert-that';
|
||||
|
||||
export default function KoaGuardSessionAction<StateT, ContextT, ResponseBodyT>(
|
||||
provider: Provider,
|
||||
forType: 'sign-in' | 'register'
|
||||
): MiddlewareType<StateT, ContextT, ResponseBodyT> {
|
||||
const forbiddenError = new RequestError({ code: 'auth.forbidden', status: 403 });
|
||||
|
||||
return async (ctx, next) => {
|
||||
const interaction = await provider
|
||||
.interactionDetails(ctx.req, ctx.res)
|
||||
.catch((error: unknown) => {
|
||||
// Should not block if interaction is not found
|
||||
if (error instanceof errors.SessionNotFound) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
|
||||
/**
|
||||
* We don't guard admin console in API for now since logically there's no need.
|
||||
* Update to honor the config if we're implementing per-app SIE.
|
||||
*/
|
||||
if (interaction?.params.client_id === adminConsoleApplicationId) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const { signInMode } = await findDefaultSignInExperience();
|
||||
|
||||
if (forType === 'sign-in') {
|
||||
assertThat(signInMode !== SignInMode.Register, forbiddenError);
|
||||
}
|
||||
|
||||
if (forType === 'register') {
|
||||
assertThat(signInMode !== SignInMode.SignIn, forbiddenError);
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
}
|
|
@ -6,7 +6,7 @@ import { mockUser } from '@/__mocks__';
|
|||
import RequestError from '@/errors/RequestError';
|
||||
import { createRequester } from '@/utils/test-utils';
|
||||
|
||||
import sessionRoutes from '.';
|
||||
import sessionRoutes from './username-password';
|
||||
|
||||
const insertUser = jest.fn(async (..._args: unknown[]) => ({ id: 'id' }));
|
||||
const findUserById = jest.fn(async (): Promise<User> => mockUser);
|
||||
|
|
Loading…
Reference in a new issue