Skip to content

Commit

Permalink
feat(core,schemas): log extraTokenClaims exception (#5539)
Browse files Browse the repository at this point in the history
  • Loading branch information
darcyYe authored Apr 2, 2024
1 parent 866c58e commit e09318d
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 10 deletions.
9 changes: 8 additions & 1 deletion packages/console/src/consts/logs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { AuditLogKey, LogKey, WebhookLogKey } from '@logto/schemas';
import type { AuditLogKey, WebhookLogKey, JwtCustomizerLogKey, LogKey } from '@logto/schemas';
import { type Optional } from '@silverhand/essentials';

export const auditLogEventTitle: Record<string, Optional<string>> &
Expand Down Expand Up @@ -86,7 +86,14 @@ const webhookLogEventTitle: Record<string, Optional<string>> &
'TriggerHook.PostSignIn': undefined,
});

const jwtCustomizerLogEventTitle: Record<string, Optional<string>> &
Record<JwtCustomizerLogKey, Optional<string>> = Object.freeze({
'JwtCustomizer.AccessToken': undefined,
'JwtCustomizer.ClientCredentials': undefined,
});

export const logEventTitle: Record<string, Optional<string>> & Record<LogKey, Optional<string>> = {
...auditLogEventTitle,
...webhookLogEventTitle,
...jwtCustomizerLogEventTitle,
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { type WebhookDetailsOutletContext } from '../types';

import * as styles from './index.module.scss';

const hooLogEventOptions = Object.values(HookEvent).map((event) => ({
const hookLogEventOptions = Object.values(HookEvent).map((event) => ({
title: <DynamicT forKey={hookEventLabel[event]} />,
value: hookEventLogKey[event],
}));
Expand Down Expand Up @@ -64,7 +64,7 @@ function WebhookLogs() {
<div className={styles.eventSelector}>
<EventSelector
value={event}
options={hooLogEventOptions}
options={hookLogEventOptions}
onChange={(event) => {
updateSearchParameters({ event, page: undefined });
}}
Expand Down
41 changes: 35 additions & 6 deletions packages/core/src/oidc/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import {
LogtoJwtTokenPath,
ExtraParamsKey,
type Json,
jwtCustomizer as jwtCustomizerLog,
LogResult,
} from '@logto/schemas';
import { generateStandardId } from '@logto/shared';
import { conditional, trySafe, tryThat } from '@silverhand/essentials';
import i18next from 'i18next';
import koaBody from 'koa-body';
Expand All @@ -29,7 +32,7 @@ import RequestError from '#src/errors/RequestError/index.js';
import { addOidcEventListeners } from '#src/event-listeners/index.js';
import { type CloudConnectionLibrary } from '#src/libraries/cloud-connection.js';
import { type LogtoConfigLibrary } from '#src/libraries/logto-config.js';
import koaAuditLog from '#src/middleware/koa-audit-log.js';
import koaAuditLog, { LogEntry } from '#src/middleware/koa-audit-log.js';
import koaBodyEtag from '#src/middleware/koa-body-etag.js';
import postgresAdapter from '#src/oidc/adapter.js';
import {
Expand Down Expand Up @@ -65,6 +68,7 @@ export default function initOidc(
resources: { findDefaultResource },
users: { findUserById },
organizations,
logs: { insertLog },
} = queries;
const logoutSource = readFileSync('static/html/logout.html', 'utf8');
const logoutSuccessSource = readFileSync('static/html/post-logout/index.html', 'utf8');
Expand Down Expand Up @@ -206,7 +210,7 @@ export default function initOidc(
},
},
extraParams: Object.values(ExtraParamsKey),

// eslint-disable-next-line complexity
extraTokenClaims: async (ctx, token) => {
const { isDevFeaturesEnabled, isCloud } = EnvSet.values;

Expand All @@ -215,9 +219,14 @@ export default function initOidc(
return;
}

try {
const isTokenClientCredentials = token instanceof ctx.oidc.provider.ClientCredentials;
const isTokenClientCredentials = token instanceof ctx.oidc.provider.ClientCredentials;

try {
/**
* It is by design to use `trySafe` here to catch the error but not log it since we do not
* want to insert an error log every time the OIDC provider issues a token when the JWT
* customizer is not configured.
*/
const { script, envVars } =
(await trySafe(
logtoConfigs.getJwtCustomizer(
Expand Down Expand Up @@ -270,8 +279,28 @@ export default function initOidc(
context: { user: logtoUserInfo as Record<string, Json> },
},
});
} catch {
// TODO: Log the error
} catch (error: unknown) {
const entry = new LogEntry(
`${jwtCustomizerLog.prefix}.${
isTokenClientCredentials
? jwtCustomizerLog.Type.ClientCredentials
: jwtCustomizerLog.Type.AccessToken
}`
);
entry.append({
result: LogResult.Error,
error: { message: String(error) },
});
const { payload } = entry;
await insertLog({
id: generateStandardId(),
key: payload.key,
payload: {
...payload,
tenantId: envSet.tenantId,
token,
},
});
}
},
extraClientMetadata: {
Expand Down
5 changes: 4 additions & 1 deletion packages/schemas/src/types/log/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import type * as hook from './hook.js';
import type * as interaction from './interaction.js';
import type * as jwtCustomizer from './jwt-customizer.js';
import type * as token from './token.js';

export * as interaction from './interaction.js';
export * as token from './token.js';
export * as hook from './hook.js';
export * as jwtCustomizer from './jwt-customizer.js';

/** Fallback for empty or unrecognized log keys. */
export const LogKeyUnknown = 'Unknown';

export type AuditLogKey = typeof LogKeyUnknown | interaction.LogKey | token.LogKey;
export type WebhookLogKey = hook.LogKey;
export type JwtCustomizerLogKey = jwtCustomizer.LogKey;

/**
* The union type of all available log keys.
Expand All @@ -19,4 +22,4 @@ export type WebhookLogKey = hook.LogKey;
* @see {@link interaction.LogKey} for interaction log keys.
* @see {@link token.LogKey} for token log keys.
**/
export type LogKey = AuditLogKey | WebhookLogKey;
export type LogKey = AuditLogKey | WebhookLogKey | JwtCustomizerLogKey;
11 changes: 11 additions & 0 deletions packages/schemas/src/types/log/jwt-customizer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export type Prefix = 'JwtCustomizer';

export const prefix: Prefix = 'JwtCustomizer';

/** The type of a custom JWT scenario. */
export enum Type {
AccessToken = 'AccessToken',
ClientCredentials = 'ClientCredentials',
}

export type LogKey = `${Prefix}.${Type.AccessToken | Type.ClientCredentials}`;

0 comments on commit e09318d

Please sign in to comment.