Skip to content

Commit

Permalink
chore: update cloud version and the way to call cloud custom JWT API
Browse files Browse the repository at this point in the history
  • Loading branch information
darcyYe committed Mar 28, 2024
1 parent 961fd8e commit 48cfdf5
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 44 deletions.
2 changes: 1 addition & 1 deletion packages/connectors/connector-logto-email/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@
"access": "public"
},
"devDependencies": {
"@logto/cloud": "0.2.5-81f06ea"
"@logto/cloud": "0.2.5-2a777a1"
}
}
2 changes: 1 addition & 1 deletion packages/console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@fontsource/roboto-mono": "^5.0.0",
"@jest/types": "^29.5.0",
"@logto/app-insights": "workspace:^1.4.0",
"@logto/cloud": "0.2.5-81f06ea",
"@logto/cloud": "0.2.5-2a777a1",
"@logto/connector-kit": "workspace:^2.1.0",
"@logto/core-kit": "workspace:^2.3.0",
"@logto/language-kit": "workspace:^1.1.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"zod": "^3.22.4"
},
"devDependencies": {
"@logto/cloud": "0.2.5-81f06ea",
"@logto/cloud": "0.2.5-2a777a1",
"@silverhand/eslint-config": "5.0.0",
"@silverhand/ts-config": "5.0.0",
"@types/debug": "^4.1.7",
Expand Down
27 changes: 21 additions & 6 deletions packages/core/src/oidc/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import {
logtoCookieKey,
type LogtoUiCookie,
LogtoJwtTokenKey,
LogtoJwtTokenPath,
ExtraParamsKey,
type Json,
} from '@logto/schemas';
import { conditional, trySafe, tryThat } from '@silverhand/essentials';
import i18next from 'i18next';
Expand Down Expand Up @@ -204,6 +206,7 @@ export default function initOidc(
},
},
extraParams: Object.values(ExtraParamsKey),

extraTokenClaims: async (ctx, token) => {
const { isDevFeaturesEnabled, isCloud } = EnvSet.values;

Expand Down Expand Up @@ -239,6 +242,12 @@ export default function initOidc(

const client = await cloudConnection.getClient();

const commonPayload = {
script,
envVars,
token: readOnlyToken,
};

// We pass context to the cloud API only when it is a user's access token.
const logtoUserInfo = conditional(
!isTokenClientCredentials &&
Expand All @@ -248,12 +257,18 @@ export default function initOidc(

// `context` parameter is only eligible for user's access token for now.
return await client.post(`/api/services/custom-jwt`, {
body: {
script,
envVars,
token: readOnlyToken,
...conditional(logtoUserInfo && { context: { user: logtoUserInfo } }),
},
body: isTokenClientCredentials
? {
...commonPayload,
tokenType: LogtoJwtTokenPath.ClientCredentials,
}
: {
...commonPayload,
tokenType: LogtoJwtTokenPath.AccessToken,
// TODO (LOG-8555): the newly added `UserProfile` type includes undefined fields and can not be directly assigned to `Json` type. And the `undefined` fields should be removed by zod guard.

Check warning on line 268 in packages/core/src/oidc/init.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/core/src/oidc/init.ts#L268

[no-warning-comments] Unexpected 'todo' comment: 'TODO (LOG-8555): the newly added...'.
// eslint-disable-next-line no-restricted-syntax
context: { user: logtoUserInfo as Record<string, Json> },
},
});
} catch {
// TODO: Log the error

Check warning on line 274 in packages/core/src/oidc/init.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/core/src/oidc/init.ts#L274

[no-warning-comments] Unexpected 'todo' comment: 'TODO: Log the error'.
Expand Down
63 changes: 37 additions & 26 deletions packages/core/src/routes/logto-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import {
LogtoJwtTokenKey,
LogtoJwtTokenPath,
jsonObjectGuard,
type CustomJwtFetcher,
jwtCustomizerTestRequestBodyGuard,
type JwtCustomizerTestRequestBody,
} from '@logto/schemas';
import { adminTenantId } from '@logto/schemas';
import { ResponseError } from '@withtyped/client';
Expand Down Expand Up @@ -50,6 +53,37 @@ const getJwtTokenKeyAndBody = (tokenPath: LogtoJwtTokenPath, body: unknown) => {
};
};

/**
* Transpile the request body of the JWT customizer test API to the request body of the Cloud JWT customizer test API.
*
* @param body Core JWT customizer test API request body.
* @returns Request body of the Cloud JWT customizer test API.
*/
const transpileJwtCustomizerTestRequestBody = (
body: JwtCustomizerTestRequestBody
): CustomJwtFetcher => {
const { tokenType, payload } = body;
/**
* We have to deal with the `tokenType` and `payload` at the same time since they are put together as one of the discriminated union type.
* Otherwise the type inference will not work as expected.
*/
if (tokenType === LogtoJwtTokenPath.AccessToken) {
const { tokenSample: token, contextSample: context, ...rest } = payload;
return {
tokenType,
token,
context,
...rest,
};
}
const { tokenSample: token, contextSample, ...rest } = payload;
return {
tokenType,
token,
...rest,
};
};

/**
* Remove actual values of the private keys from response.
* @param type Logto config key DB column name. Values are either `oidc.privateKeys` or `oidc.cookieKeys`.
Expand Down Expand Up @@ -314,41 +348,18 @@ export default function logtoConfigRoutes<T extends AuthedRouter>(
* 1. no `script` provided.
* 2. no `tokenSample` provided.
*/
body: z.discriminatedUnion('tokenType', [
z.object({
tokenType: z.literal(LogtoJwtTokenPath.AccessToken),
payload: accessTokenJwtCustomizerGuard.required({
script: true,
tokenSample: true,
}),
}),
z.object({
tokenType: z.literal(LogtoJwtTokenPath.ClientCredentials),
payload: clientCredentialsJwtCustomizerGuard.required({
script: true,
tokenSample: true,
}),
}),
]),
body: jwtCustomizerTestRequestBodyGuard,
response: jsonObjectGuard,
status: [200, 400, 403, 422],
}),
async (ctx, next) => {
const {
body: {
payload: { tokenSample, contextSample, ...rest },
},
} = ctx.guard;
const { body } = ctx.guard;

const client = await cloudConnection.getClient();

try {
ctx.body = await client.post(`/api/services/custom-jwt`, {
body: {
...rest,
token: tokenSample,
context: contextSample,
},
body: transpileJwtCustomizerTestRequestBody(body),
});
} catch (error: unknown) {
/**
Expand Down
29 changes: 28 additions & 1 deletion packages/schemas/src/types/jwt-customizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { z } from 'zod';
import { Roles, UserSsoIdentities, Organizations } from '../db-entries/index.js';
import { jsonObjectGuard, mfaFactorsGuard } from '../foundations/index.js';

import { jwtCustomizerGuard } from './logto-config/index.js';
import {
jwtCustomizerGuard,
accessTokenJwtCustomizerGuard,
clientCredentialsJwtCustomizerGuard,
} from './logto-config/index.js';
import { scopeResponseGuard } from './scope.js';
import { userInfoGuard } from './user.js';

Expand Down Expand Up @@ -37,6 +41,29 @@ export enum LogtoJwtTokenPath {
ClientCredentials = 'client-credentials',
}

/**
* This guard is for the core JWT customizer testing API request body guard.
*/
export const jwtCustomizerTestRequestBodyGuard = z.discriminatedUnion('tokenType', [
z.object({
tokenType: z.literal(LogtoJwtTokenPath.AccessToken),
payload: accessTokenJwtCustomizerGuard.required({
script: true,
tokenSample: true,
contextSample: true,
}),
}),
z.object({
tokenType: z.literal(LogtoJwtTokenPath.ClientCredentials),
payload: clientCredentialsJwtCustomizerGuard.required({
script: true,
tokenSample: true,
}),
}),
]);

export type JwtCustomizerTestRequestBody = z.infer<typeof jwtCustomizerTestRequestBodyGuard>;

/**
* This guard is for cloud API use (request body guard).
* Since the cloud API will be use by both testing and production, should keep the fields as general as possible.
Expand Down
19 changes: 11 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 48cfdf5

Please sign in to comment.