From a8a3de35443cec485a435d51b452af0f9a56ed28 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Tue, 23 Aug 2022 18:29:05 +0800 Subject: [PATCH] feat(core): guard session with sign-in mode --- packages/core/src/routes/session/index.ts | 4 ++ .../middleware/koa-guard-session-action.ts | 48 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 packages/core/src/routes/session/middleware/koa-guard-session-action.ts diff --git a/packages/core/src/routes/session/index.ts b/packages/core/src/routes/session/index.ts index 3c6202fa412..9cde41dce0e 100644 --- a/packages/core/src/routes/session/index.ts +++ b/packages/core/src/routes/session/index.ts @@ -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(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 }, diff --git a/packages/core/src/routes/session/middleware/koa-guard-session-action.ts b/packages/core/src/routes/session/middleware/koa-guard-session-action.ts new file mode 100644 index 00000000000..ee756e134d4 --- /dev/null +++ b/packages/core/src/routes/session/middleware/koa-guard-session-action.ts @@ -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( + provider: Provider, + forType: 'sign-in' | 'register' +): MiddlewareType { + 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(); + }; +}