From 60a23f1b19654657072b31d01ea0b9312a8c60bb Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Tue, 8 Nov 2022 20:30:51 +0800 Subject: [PATCH] refactor(core): throw proper error in OIDC functions (#2331) --- packages/core/nodemon.json | 2 +- packages/core/src/oidc/adapter.test.ts | 5 ----- packages/core/src/oidc/adapter.ts | 6 +++++- packages/core/src/oidc/init.ts | 12 ++++++++++-- packages/shared/src/utils/function.ts | 16 ++++++++++++++++ packages/shared/src/utils/index.ts | 1 + 6 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 packages/shared/src/utils/function.ts diff --git a/packages/core/nodemon.json b/packages/core/nodemon.json index 59cbcbe33..7c1e17a4a 100644 --- a/packages/core/nodemon.json +++ b/packages/core/nodemon.json @@ -1,5 +1,5 @@ { - "exec": "tsc -p tsconfig.build.json --incremental && node ./build/index.js", + "exec": "tsc -p tsconfig.build.json --incremental && node ./build/index.js || exit 1", "ignore": [ "node_modules/**/node_modules" ], diff --git a/packages/core/src/oidc/adapter.test.ts b/packages/core/src/oidc/adapter.test.ts index 8ee40b08e..c5ad29faa 100644 --- a/packages/core/src/oidc/adapter.test.ts +++ b/packages/core/src/oidc/adapter.test.ts @@ -27,11 +27,6 @@ jest.mock('@/queries/oidc-model-instance', () => ({ revokeInstanceByGrantId: jest.fn(), })); -jest.mock('@logto/shared', () => ({ - // eslint-disable-next-line unicorn/consistent-function-scoping - buildIdGenerator: jest.fn(() => () => 'randomId'), -})); - const now = Date.now(); jest.mock( diff --git a/packages/core/src/oidc/adapter.ts b/packages/core/src/oidc/adapter.ts index dc401c715..9dd988cb1 100644 --- a/packages/core/src/oidc/adapter.ts +++ b/packages/core/src/oidc/adapter.ts @@ -1,8 +1,10 @@ import type { CreateApplication, OidcClientMetadata } from '@logto/schemas'; import { ApplicationType } from '@logto/schemas'; import { adminConsoleApplicationId, demoAppApplicationId } from '@logto/schemas/lib/seeds'; +import { tryThat } from '@logto/shared'; import { addSeconds } from 'date-fns'; import type { AdapterFactory, AllClientMetadata } from 'oidc-provider'; +import { errors } from 'oidc-provider'; import snakecaseKeys from 'snakecase-keys'; import envSet, { MountedApps } from '@/env-set'; @@ -83,7 +85,9 @@ export default function postgresAdapter(modelName: string): ReturnType { extraTokenClaims: async (_ctx, token) => { if (token.kind === 'AccessToken') { const { accountId } = token; - const { roleNames } = await findUserById(accountId); + const { roleNames } = await tryThat( + findUserById(accountId), + new errors.InvalidClient(`invalid user ${accountId}`) + ); return snakecaseKeys({ roleNames, @@ -172,7 +176,11 @@ export default async function initOidc(app: Koa): Promise { // `token.kind === 'ClientCredentials'` const { clientId } = token; assertThat(clientId, 'oidc.invalid_grant'); - const { roleNames } = await findApplicationById(clientId); + + const { roleNames } = await tryThat( + findApplicationById(clientId), + new errors.InvalidClient(`invalid client ${clientId}`) + ); return snakecaseKeys({ roleNames }); }, diff --git a/packages/shared/src/utils/function.ts b/packages/shared/src/utils/function.ts new file mode 100644 index 000000000..c033d8253 --- /dev/null +++ b/packages/shared/src/utils/function.ts @@ -0,0 +1,16 @@ +export const tryThat = async ( + exec: Promise | (() => Promise), + onError: E | ((error: unknown) => never) +): Promise => { + try { + return await (typeof exec === 'function' ? exec() : exec); + } catch (error: unknown) { + if (onError instanceof Error) { + // https://github.com/typescript-eslint/typescript-eslint/issues/3814 + // eslint-disable-next-line @typescript-eslint/no-throw-literal + throw onError; + } + + return onError(error); + } +}; diff --git a/packages/shared/src/utils/index.ts b/packages/shared/src/utils/index.ts index 357301f3a..3912ce027 100644 --- a/packages/shared/src/utils/index.ts +++ b/packages/shared/src/utils/index.ts @@ -1,2 +1,3 @@ export * from './id'; +export * from './function'; export { default as findPackage } from './find-package';