Add challenge token

This commit is contained in:
Fang-Pen Lin
2025-11-07 09:18:42 -08:00
parent a7f773b78f
commit 1319ccc0d3
4 changed files with 23 additions and 16 deletions
@@ -104,6 +104,9 @@ export async function up(knex: Knex): Promise<void> {
// Authorization status // Authorization status
t.string("status").notNullable(); // pending, valid, invalid, deactivated, expired, revoked t.string("status").notNullable(); // pending, valid, invalid, deactivated, expired, revoked
// Token used to validate the authorization through ACME challenge
t.timestamp("token").nullable();
// Identifier type and value // Identifier type and value
t.string("identifierType").notNullable(); // dns t.string("identifierType").notNullable(); // dns
t.string("identifierValue").notNullable(); // domain name t.string("identifierValue").notNullable(); // domain name
+1 -1
View File
@@ -96,8 +96,8 @@ export * from "./pki-acme-accounts";
export * from "./pki-acme-auths"; export * from "./pki-acme-auths";
export * from "./pki-acme-challenges"; export * from "./pki-acme-challenges";
export * from "./pki-acme-enrollment-configs"; export * from "./pki-acme-enrollment-configs";
export * from "./pki-acme-orders";
export * from "./pki-acme-order-auths"; export * from "./pki-acme-order-auths";
export * from "./pki-acme-orders";
export * from "./pki-alerts"; export * from "./pki-alerts";
export * from "./pki-api-enrollment-configs"; export * from "./pki-api-enrollment-configs";
export * from "./pki-certificate-profiles"; export * from "./pki-certificate-profiles";
+2 -1
View File
@@ -16,7 +16,8 @@ export const PkiAcmeAuthsSchema = z.object({
expiresAt: z.date(), expiresAt: z.date(),
certificateId: z.string().uuid().nullable().optional(), certificateId: z.string().uuid().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date() updatedAt: z.date(),
token: z.string().nullable().optional()
}); });
export type TPkiAcmeAuths = z.infer<typeof PkiAcmeAuthsSchema>; export type TPkiAcmeAuths = z.infer<typeof PkiAcmeAuthsSchema>;
@@ -1,19 +1,11 @@
import { getConfig } from "@app/lib/config/env";
import { NotFoundError } from "@app/lib/errors";
import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal";
import {
AcmeAccountDoesNotExistError,
AcmeBadPublicKeyError,
AcmeMalformedError,
AcmeServerInternalError,
AcmeUnsupportedIdentifierError
} from "./pki-acme-errors";
import { TPkiAcmeAccounts } from "@app/db/schemas/pki-acme-accounts"; import { TPkiAcmeAccounts } from "@app/db/schemas/pki-acme-accounts";
import { TPkiAcmeAuths } from "@app/db/schemas/pki-acme-auths"; import { TPkiAcmeAuths } from "@app/db/schemas/pki-acme-auths";
import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto/cryptography";
import { NotFoundError } from "@app/lib/errors";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal";
import { import {
EnrollmentType, EnrollmentType,
TCertificateProfileWithConfigs TCertificateProfileWithConfigs
@@ -22,6 +14,13 @@ import { errors, flattenedVerify, FlattenedVerifyResult, importJWK, JWSHeaderPar
import { z, ZodError } from "zod"; import { z, ZodError } from "zod";
import { TPkiAcmeAccountDALFactory } from "./pki-acme-account-dal"; import { TPkiAcmeAccountDALFactory } from "./pki-acme-account-dal";
import { TPkiAcmeAuthDALFactory } from "./pki-acme-auth-dal"; import { TPkiAcmeAuthDALFactory } from "./pki-acme-auth-dal";
import {
AcmeAccountDoesNotExistError,
AcmeBadPublicKeyError,
AcmeMalformedError,
AcmeServerInternalError,
AcmeUnsupportedIdentifierError
} from "./pki-acme-errors";
import { TPkiAcmeOrderAuthDALFactory } from "./pki-acme-order-auth-dal"; import { TPkiAcmeOrderAuthDALFactory } from "./pki-acme-order-auth-dal";
import { TPkiAcmeOrderDALFactory } from "./pki-acme-order-dal"; import { TPkiAcmeOrderDALFactory } from "./pki-acme-order-dal";
import { import {
@@ -32,6 +31,7 @@ import {
ProtectedHeaderSchema ProtectedHeaderSchema
} from "./pki-acme-schemas"; } from "./pki-acme-schemas";
import { import {
TAcmeOrderResource,
TAcmeResponse, TAcmeResponse,
TAuthenciatedJwsPayload, TAuthenciatedJwsPayload,
TCreateAcmeAccountPayload, TCreateAcmeAccountPayload,
@@ -44,7 +44,6 @@ import {
TGetAcmeDirectoryResponse, TGetAcmeDirectoryResponse,
TJwsPayload, TJwsPayload,
TListAcmeOrdersResponse, TListAcmeOrdersResponse,
TAcmeOrderResource,
TPkiAcmeServiceFactory, TPkiAcmeServiceFactory,
TRawJwsPayload, TRawJwsPayload,
TRespondToAcmeChallengeResponse TRespondToAcmeChallengeResponse
@@ -357,6 +356,10 @@ export const pkiAcmeServiceFactory = ({
status: AcmeAuthStatus.Pending, status: AcmeAuthStatus.Pending,
identifierType: identifier.type, identifierType: identifier.type,
identifierValue: identifier.value, identifierValue: identifier.value,
// RFC 8555 suggests a token with at least 128 bits of entropy
// We are using 256 bits of entropy here, should be enough for now
// ref: https://datatracker.ietf.org/doc/html/rfc8555#section-11.3
token: crypto.randomBytes(32).toString("base64"),
// TODO: read config from the profile to get the expiration time instead // TODO: read config from the profile to get the expiration time instead
expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000) expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000)
}, },