mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-03 20:26:05 +00:00
More for validate jws payload
This commit is contained in:
@@ -1,12 +1,17 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export const ProtectedHeaderSchema = z.object({
|
export const ProtectedHeaderSchema = z
|
||||||
alg: z.string(),
|
.object({
|
||||||
nonce: z.string(),
|
alg: z.string(),
|
||||||
url: z.string(),
|
nonce: z.string(),
|
||||||
kid: z.string().optional(),
|
url: z.string(),
|
||||||
jwk: z.record(z.string(), z.string()).optional()
|
kid: z.string().optional(),
|
||||||
});
|
jwk: z.record(z.string(), z.string()).optional()
|
||||||
|
})
|
||||||
|
.refine((data) => data.kid || data.jwk, {
|
||||||
|
message: "Either kid or jwk must be provided",
|
||||||
|
path: ["kid", "jwk"]
|
||||||
|
});
|
||||||
|
|
||||||
// Raw JWS payload schema before parsing and verification
|
// Raw JWS payload schema before parsing and verification
|
||||||
export const RawJwsPayloadSchema = z.object({
|
export const RawJwsPayloadSchema = z.object({
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
import { NotFoundError } from "@app/lib/errors";
|
||||||
|
|
||||||
import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal";
|
import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal";
|
||||||
|
|
||||||
import { AcmeMalformedError, AcmeBadPublicKeyError } from "./pki-acme-errors";
|
import { AcmeBadPublicKeyError, AcmeMalformedError } from "./pki-acme-errors";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EnrollmentType,
|
EnrollmentType,
|
||||||
TCertificateProfileWithConfigs
|
TCertificateProfileWithConfigs
|
||||||
} from "@app/services/certificate-profile/certificate-profile-types";
|
} from "@app/services/certificate-profile/certificate-profile-types";
|
||||||
|
import { flattenedVerify, importJWK, JWK, JWSHeaderParameters } from "jose";
|
||||||
|
import { ProtectedHeaderSchema } from "./pki-acme-schemas";
|
||||||
import {
|
import {
|
||||||
TCreateAcmeAccountPayload,
|
TCreateAcmeAccountPayload,
|
||||||
TCreateAcmeAccountResponse,
|
TCreateAcmeAccountResponse,
|
||||||
@@ -21,14 +23,12 @@ import {
|
|||||||
TGetAcmeAuthorizationResponse,
|
TGetAcmeAuthorizationResponse,
|
||||||
TGetAcmeDirectoryResponse,
|
TGetAcmeDirectoryResponse,
|
||||||
TGetAcmeOrderResponse,
|
TGetAcmeOrderResponse,
|
||||||
TRawJwsPayload,
|
TJwsPayload,
|
||||||
TListAcmeOrdersResponse,
|
TListAcmeOrdersResponse,
|
||||||
TPkiAcmeServiceFactory,
|
TPkiAcmeServiceFactory,
|
||||||
TRespondToAcmeChallengeResponse,
|
TRawJwsPayload,
|
||||||
TJwsPayload,
|
TRespondToAcmeChallengeResponse
|
||||||
TProtectedHeader
|
|
||||||
} from "./pki-acme-types";
|
} from "./pki-acme-types";
|
||||||
import { flattenedVerify, importJWK, JWK, JWSHeaderParameters } from "jose";
|
|
||||||
|
|
||||||
type TPkiAcmeServiceFactoryDep = {
|
type TPkiAcmeServiceFactoryDep = {
|
||||||
certificateProfileDAL: Pick<TCertificateProfileDALFactory, "findById">;
|
certificateProfileDAL: Pick<TCertificateProfileDALFactory, "findById">;
|
||||||
@@ -52,9 +52,9 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
|
|||||||
return `${baseUrl}${path}`;
|
return `${baseUrl}${path}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateCreateAcmeAccountJwsPayload = async (rawPayload: TRawJwsPayload): Promise<TJwsPayload> => {
|
const validateCreateAcmeAccountJwsPayload = async (rawJwsPayload: TRawJwsPayload): Promise<TJwsPayload> => {
|
||||||
const { payload, protectedHeader } = await flattenedVerify(
|
const { payload: rawPayload, protectedHeader: rawProtectedHeader } = await flattenedVerify(
|
||||||
rawPayload,
|
rawJwsPayload,
|
||||||
async (protectedHeader: JWSHeaderParameters | undefined) => {
|
async (protectedHeader: JWSHeaderParameters | undefined) => {
|
||||||
if (protectedHeader === undefined) {
|
if (protectedHeader === undefined) {
|
||||||
throw new AcmeMalformedError({ detail: "Protected header is required" });
|
throw new AcmeMalformedError({ detail: "Protected header is required" });
|
||||||
@@ -68,10 +68,14 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
|
|||||||
return imported;
|
return imported;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
const { success, data: protectedHeader } = ProtectedHeaderSchema.safeParse(rawProtectedHeader);
|
||||||
|
if (!success) {
|
||||||
|
throw new AcmeMalformedError({ detail: "Invalid protected header" });
|
||||||
|
}
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder();
|
||||||
const parsedPayload = JSON.parse(decoder.decode(payload)) as TCreateAcmeAccountPayload;
|
const payload = JSON.parse(decoder.decode(rawPayload)) as TCreateAcmeAccountPayload;
|
||||||
// TODO: also consume the nonce here
|
// TODO: also consume the nonce here
|
||||||
return { payload: parsedPayload, protectedHeader: protectedHeader as TProtectedHeader };
|
return { payload, protectedHeader };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAcmeDirectory = async (profileId: string): Promise<TGetAcmeDirectoryResponse> => {
|
const getAcmeDirectory = async (profileId: string): Promise<TGetAcmeDirectoryResponse> => {
|
||||||
|
|||||||
Reference in New Issue
Block a user