Skip to content

Commit

Permalink
feat(core): guard session with sign-in mode
Browse files Browse the repository at this point in the history
  • Loading branch information
gao-sun committed Aug 23, 2022
1 parent 3d67639 commit a8a3de3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
4 changes: 4 additions & 0 deletions packages/core/src/routes/session/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
};
}

0 comments on commit a8a3de3

Please sign in to comment.