diff --git a/packages/core/src/event-listeners/grant.ts b/packages/core/src/event-listeners/grant.ts index d767eea03..fa18dc94d 100644 --- a/packages/core/src/event-listeners/grant.ts +++ b/packages/core/src/event-listeners/grant.ts @@ -71,6 +71,7 @@ const grantTypeToExchangeByType: Record = { [GrantType.RefreshToken]: token.ExchangeByType.RefreshToken, [GrantType.ClientCredentials]: token.ExchangeByType.ClientCredentials, [GrantType.TokenExchange]: token.ExchangeByType.TokenExchange, + [GrantType.Implicit]: token.ExchangeByType.Implicit, }; const getExchangeByType = (grantType: unknown): token.ExchangeByType => { diff --git a/packages/core/src/routes/applications/application.ts b/packages/core/src/routes/applications/application.ts index 2794114b2..97aa05ea8 100644 --- a/packages/core/src/routes/applications/application.ts +++ b/packages/core/src/routes/applications/application.ts @@ -260,7 +260,7 @@ export default function applicationRoutes( body, } = ctx.guard; - const { isAdmin, protectedAppMetadata, ...rest } = body; + const { isAdmin, protectedAppMetadata, oidcClientMetadata, ...rest } = body; // @deprecated // User can enable the admin access of Machine-to-Machine apps by switching on a toggle on Admin Console. @@ -319,6 +319,12 @@ export default function applicationRoutes( } } + // Prevent hidden fields (grantTypes, responseTypes) from being replaced + // Merge oidcClientMetadata if it's provided + if (oidcClientMetadata) { + await queries.applications.updateApplicationById(id, { oidcClientMetadata }, 'merge'); + } + ctx.body = await (Object.keys(rest).length > 0 ? queries.applications.updateApplicationById(id, rest, 'replace') : queries.applications.findApplicationById(id)); diff --git a/packages/core/src/routes/applications/types.ts b/packages/core/src/routes/applications/types.ts index 33ca10fc9..760a1f39b 100644 --- a/packages/core/src/routes/applications/types.ts +++ b/packages/core/src/routes/applications/types.ts @@ -1,4 +1,5 @@ import { + oidcClientMetadataGuard, applicationCreateGuard as originalApplicationCreateGuard, applicationPatchGuard as originalApplicationPatchGuard, } from '@logto/schemas'; @@ -7,6 +8,7 @@ import { z } from 'zod'; export const applicationCreateGuard = originalApplicationCreateGuard .omit({ protectedAppMetadata: true, + oidcClientMetadata: true, }) .extend({ protectedAppMetadata: z @@ -15,11 +17,19 @@ export const applicationCreateGuard = originalApplicationCreateGuard origin: z.string(), }) .optional(), + // Prevent setting grantTypes and responseTypes in the create guard + oidcClientMetadata: oidcClientMetadataGuard + .omit({ + grantTypes: true, + responseTypes: true, + }) + .optional(), }); export const applicationPatchGuard = originalApplicationPatchGuard .omit({ protectedAppMetadata: true, + oidcClientMetadata: true, }) .extend({ protectedAppMetadata: z @@ -36,4 +46,11 @@ export const applicationPatchGuard = originalApplicationPatchGuard .optional(), }) .optional(), + // Prevent setting grantTypes and responseTypes in the create guard + oidcClientMetadata: oidcClientMetadataGuard + .omit({ + grantTypes: true, + responseTypes: true, + }) + .optional(), }); diff --git a/packages/schemas/src/types/log/token.ts b/packages/schemas/src/types/log/token.ts index d1b640418..d6eaae199 100644 --- a/packages/schemas/src/types/log/token.ts +++ b/packages/schemas/src/types/log/token.ts @@ -21,6 +21,7 @@ export enum ExchangeByType { RefreshToken = 'RefreshToken', ClientCredentials = 'ClientCredentials', TokenExchange = 'TokenExchange', + Implicit = 'Implicit', } export type LogKey = `${Type.ExchangeTokenBy}.${ExchangeByType}` | `${Type.RevokeToken}`;