0
Fork 0
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:
Gao Sun 2022-08-24 14:26:57 +08:00 committed by GitHub
commit a2043a6804
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 1 deletions

View file

@ -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 },

View file

@ -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();
};
}

View file

@ -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);