0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-06 20:40:08 -05:00

refactor(core): use audit log middleware on-demand

This commit is contained in:
Gao Sun 2022-12-16 23:41:45 +08:00
parent 854e1e5751
commit 1476b8ea3a
No known key found for this signature in database
GPG key ID: 13EBE123E4773688
7 changed files with 31 additions and 20 deletions

View file

@ -9,7 +9,6 @@ import koaLogger from 'koa-logger';
import mount from 'koa-mount'; import mount from 'koa-mount';
import envSet, { MountedApps } from '#src/env-set/index.js'; import envSet, { MountedApps } from '#src/env-set/index.js';
import koaAuditLog from '#src/middleware/koa-audit-log.js';
import koaCheckDemoApp from '#src/middleware/koa-check-demo-app.js'; import koaCheckDemoApp from '#src/middleware/koa-check-demo-app.js';
import koaConnectorErrorHandler from '#src/middleware/koa-connector-error-handler.js'; import koaConnectorErrorHandler from '#src/middleware/koa-connector-error-handler.js';
import koaErrorHandler from '#src/middleware/koa-error-handler.js'; import koaErrorHandler from '#src/middleware/koa-error-handler.js';
@ -37,7 +36,6 @@ export default async function initApp(app: Koa): Promise<void> {
app.use(koaOIDCErrorHandler()); app.use(koaOIDCErrorHandler());
app.use(koaSlonikErrorHandler()); app.use(koaSlonikErrorHandler());
app.use(koaConnectorErrorHandler()); app.use(koaConnectorErrorHandler());
app.use(koaAuditLog());
app.use(koaI18next()); app.use(koaI18next());
const provider = await initOidc(app); const provider = await initOidc(app);

View file

@ -16,7 +16,7 @@ export default function koaAuditLogSession<StateT, ContextT extends WithLogConte
} = await provider.interactionDetails(ctx.req, ctx.res); } = await provider.interactionDetails(ctx.req, ctx.res);
ctx.log({ sessionId: jti, applicationId: String(client_id) }); ctx.log({ sessionId: jti, applicationId: String(client_id) });
} catch (error: unknown) { } catch (error: unknown) {
console.error(`"${ctx.url}" failed to get oidc provider interaction`, error); console.error(`Failed to get oidc provider interaction`, error);
} }
}; };
} }

View file

@ -19,7 +19,7 @@ export default function koaLogSessionLegacy<
} = await provider.interactionDetails(ctx.req, ctx.res); } = await provider.interactionDetails(ctx.req, ctx.res);
ctx.addLogContext({ sessionId: jti, applicationId: String(client_id) }); ctx.addLogContext({ sessionId: jti, applicationId: String(client_id) });
} catch (error: unknown) { } catch (error: unknown) {
console.error(`"${ctx.url}" failed to get oidc provider interaction`, error); console.error(`Failed to get oidc provider interaction`, error);
} }
}; };
} }

View file

@ -11,6 +11,7 @@ import { Provider, errors } from 'oidc-provider';
import snakecaseKeys from 'snakecase-keys'; import snakecaseKeys from 'snakecase-keys';
import envSet from '#src/env-set/index.js'; import envSet from '#src/env-set/index.js';
import koaAuditLog from '#src/middleware/koa-audit-log.js';
import postgresAdapter from '#src/oidc/adapter.js'; import postgresAdapter from '#src/oidc/adapter.js';
import { isOriginAllowed, validateCustomClientMetadata } from '#src/oidc/utils.js'; import { isOriginAllowed, validateCustomClientMetadata } from '#src/oidc/utils.js';
import { findApplicationById } from '#src/queries/application.js'; import { findApplicationById } from '#src/queries/application.js';
@ -188,6 +189,9 @@ export default async function initOidc(app: Koa): Promise<Provider> {
addOidcEventListeners(oidc); addOidcEventListeners(oidc);
// Session audit logs
oidc.use(koaAuditLog());
app.use(mount('/oidc', oidc.app)); app.use(mount('/oidc', oidc.app));
return oidc; return oidc;

View file

@ -4,6 +4,9 @@ import mount from 'koa-mount';
import Router from 'koa-router'; import Router from 'koa-router';
import type { Provider } from 'oidc-provider'; import type { Provider } from 'oidc-provider';
import koaAuditLogLegacy from '#src/middleware/koa-audit-log-legacy.js';
import koaAuditLog from '#src/middleware/koa-audit-log.js';
import koaAuditLogSession from '../middleware/koa-audit-log-session.js'; import koaAuditLogSession from '../middleware/koa-audit-log-session.js';
import koaAuth from '../middleware/koa-auth.js'; import koaAuth from '../middleware/koa-auth.js';
import koaLogSessionLegacy from '../middleware/koa-log-session-legacy.js'; import koaLogSessionLegacy from '../middleware/koa-log-session-legacy.js';
@ -29,11 +32,11 @@ import wellKnownRoutes from './well-known.js';
const createRouters = (provider: Provider) => { const createRouters = (provider: Provider) => {
const sessionRouter: AnonymousRouterLegacy = new Router(); const sessionRouter: AnonymousRouterLegacy = new Router();
sessionRouter.use(koaLogSessionLegacy(provider)); sessionRouter.use(koaAuditLogLegacy(), koaLogSessionLegacy(provider));
sessionRoutes(sessionRouter, provider); sessionRoutes(sessionRouter, provider);
const interactionRouter: AnonymousRouter = new Router(); const interactionRouter: AnonymousRouter = new Router();
interactionRouter.use(koaAuditLogSession(provider)); interactionRouter.use(koaAuditLog(), koaAuditLogSession(provider));
interactionRoutes(interactionRouter, provider); interactionRoutes(interactionRouter, provider);
const managementRouter: AuthedRouter = new Router(); const managementRouter: AuthedRouter = new Router();

View file

@ -24,7 +24,7 @@ export const verifySocialIdentity = async (
{ connectorId, connectorData }: SocialConnectorPayload, { connectorId, connectorData }: SocialConnectorPayload,
log: LogContext['log'] log: LogContext['log']
): Promise<SocialUserInfo> => { ): Promise<SocialUserInfo> => {
log.setKey('SignIn.SocialId.Social.Submit'); log.setKey('SignIn.SocialId.Social.Create');
log({ connectorId, connectorData }); log({ connectorId, connectorData });
const userInfo = await getUserInfoByAuthCode(connectorId, connectorData); const userInfo = await getUserInfoByAuthCode(connectorId, connectorData);

View file

@ -20,10 +20,12 @@ export enum Method {
} }
export enum Action { export enum Action {
/** Submit updated info to an entity, or submit to the system. (E.g. submit an interaction, submit a verification code to get verified) */
Submit = 'Submit',
/** Create a new entity. (E.g. create an interaction, create a verification code) */ /** Create a new entity. (E.g. create an interaction, create a verification code) */
Create = 'Create', Create = 'Create',
/** Update an existing entity. (E.g. change interaction type) */
Update = 'Update',
/** Submit updated info to an entity, or submit to the system. (E.g. submit an interaction, submit a verification code to get verified) */
Submit = 'Submit',
} }
/** /**
@ -44,7 +46,7 @@ export enum Action {
export type ForgotPasswordLogKey = `${Flow.ForgotPassword}.${Exclude< export type ForgotPasswordLogKey = `${Flow.ForgotPassword}.${Exclude<
Identifier, Identifier,
'SocialId' 'SocialId'
>}.${Method.VerificationCode}.${Action}`; >}.${Method.VerificationCode}.${Action.Create | Action.Submit}`;
type SignInRegisterFlow = Exclude<Flow, 'ForgotPassword'>; type SignInRegisterFlow = Exclude<Flow, 'ForgotPassword'>;
@ -57,15 +59,18 @@ type SignInRegisterFlow = Exclude<Flow, 'ForgotPassword'>;
* *
* Restrictions: * Restrictions:
* *
* - For social identifier and method, the value can only be `SignIn.SocialId.Social.Submit`. * - For social identifier and method, the value can only be `SignIn.SocialId.Social.Create`.
* - For password method, the action can only be `Submit`. * - For password method, the action can only be `Create`.
* - For verification code method, the action can be `Create` or `Submit`.
* *
* @see {@link SignInRegisterFlow}, {@link Identifier}, {@link Method}, {@link Action} for all available enums. * @see {@link SignInRegisterFlow}, {@link Identifier}, {@link Method}, {@link Action} for all available enums.
*/ */
export type SignInRegisterLogKey = export type SignInRegisterLogKey =
| `${Flow.SignIn}.${Identifier.SocialId}.${Method.Social}.${Action.Submit}` | `${Flow.SignIn}.${Identifier.SocialId}.${Method.Social}.${Action.Create}`
| `${SignInRegisterFlow}.${Exclude<Identifier, 'SocialId'>}.${Method.Password}.${Action.Submit}` | `${SignInRegisterFlow}.${Exclude<Identifier, 'SocialId'>}.${Method.Password}.${Action.Create}`
| `${SignInRegisterFlow}.${Exclude<Identifier, 'SocialId'>}.${Method.VerificationCode}.${Action}`; | `${SignInRegisterFlow}.${Exclude<Identifier, 'SocialId'>}.${Method.VerificationCode}.${
| Action.Create
| Action.Submit}`;
export type FlowLogKey = `${Flow}.${Action}`; export type FlowLogKey = `${Flow}.${Action}`;
@ -81,14 +86,15 @@ export type FlowLogKey = `${Flow}.${Action}`;
* *
* The key MUST describe an {@link Action}: * The key MUST describe an {@link Action}:
* *
* - {@link Action.Submit} (submit updated info to an entity, or submit to the system); * - {@link Action.Create} (Create a new entity);
* - {@link Action.Create} (create a new entity). * - {@link Action.Update} (Update an existing entity.);
* - {@link Action.Submit} (Submit updated info to an entity, or submit to the system).
* *
* In an interaction, ONLY the interaction itself and verification codes can be created, i.e.: * In an interaction, ONLY the interaction itself and verification codes can be submitted, i.e.:
* *
* ```ts * ```ts
* `${Flow}.Create` * `${Flow}.Submit`
* `${Flow}.${Identifier}.VerificationCode.Create` * `${Flow}.${Identifier}.VerificationCode.Submit`
* ``` * ```
* *
* There may be more restrictions, please see the specific type to learn more. * There may be more restrictions, please see the specific type to learn more.