* add public client * implement PKCE * pass codeChallenge and codeChallengeMethod to handler * fixes for secure oauth flow * fix type error * clean up refresh token endpoint * only support S256 * fix type error * remove comment * add tests * fix type errors in route.test.ts * add missing support for refresh token * add e2e test for public client refresh tokens * allow pkce for confidential clients * fix type error * fix e2e * fix option pkce for confidential clients * e2e test improvements * fix test * remove only * add delay * fix e2e tests * remove only * don't skip pkce if codeChallenge is set * add service functions for token endpoint * use service function in refreshToken endpoint * use repository * remove return types * e2e test fixes * fix e2e test * remove .only in e2e test * remove pause * fix error responses in token endpoints * adjust tests to new error responses * fix error responses * e2e improvements * redirect on error * adjust tests * Update apps/web/modules/auth/oauth2/authorize-view.tsx Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import { randomBytes, createHash } from "crypto";
|
|
|
|
import { prisma } from "@calcom/prisma";
|
|
import { Prisma } from "@calcom/prisma/client";
|
|
|
|
import type { TAddClientInputSchema } from "./addClient.schema";
|
|
|
|
type AddClientOptions = {
|
|
input: TAddClientInputSchema;
|
|
};
|
|
|
|
export const addClientHandler = async ({ input }: AddClientOptions) => {
|
|
const { name, redirectUri, logo, enablePkce } = input;
|
|
|
|
const clientId = randomBytes(32).toString("hex");
|
|
const clientType = enablePkce ? "PUBLIC" : "CONFIDENTIAL";
|
|
|
|
// Only generate client secret for confidential clients
|
|
const clientData: Prisma.OAuthClientCreateInput = {
|
|
name,
|
|
redirectUri,
|
|
clientId,
|
|
clientType,
|
|
logo,
|
|
};
|
|
|
|
let secret: string | undefined;
|
|
if (!enablePkce) {
|
|
const [hashedSecret, plainSecret] = generateSecret();
|
|
clientData.clientSecret = hashedSecret;
|
|
secret = plainSecret;
|
|
}
|
|
const client = await prisma.oAuthClient.create({
|
|
data: clientData,
|
|
});
|
|
|
|
return {
|
|
clientId: client.clientId,
|
|
name: client.name,
|
|
redirectUri: client.redirectUri,
|
|
logo: client.logo,
|
|
clientType: client.clientType,
|
|
clientSecret: secret, // Only return plain secret for confidential clients
|
|
isPkceEnabled: enablePkce,
|
|
};
|
|
};
|
|
|
|
const hashSecretKey = (apiKey: string): string => createHash("sha256").update(apiKey).digest("hex");
|
|
|
|
// Generate a random secret
|
|
export const generateSecret = (secret = randomBytes(32).toString("hex")) => [hashSecretKey(secret), secret];
|