Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/thirty-knives-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/clerk-js': patch
---

Adding baseline debug logging to SignIn and SignUp components
82 changes: 57 additions & 25 deletions packages/clerk-js/src/core/resources/SignIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ import type {
Web3SignatureFactor,
} from '@clerk/types';

import { debugLogger } from '@/utils/debug';

import {
generateSignatureWithBase,
generateSignatureWithCoinbaseWallet,
Expand Down Expand Up @@ -88,7 +90,7 @@ export class SignIn extends BaseResource implements SignInResource {
pathRoot = '/client/sign_ins';

id?: string;
status: SignInStatus | null = null;
private _status: SignInStatus | null = null;
supportedIdentifiers: SignInIdentifier[] = [];
supportedFirstFactors: SignInFirstFactor[] | null = [];
supportedSecondFactors: SignInSecondFactor[] | null = null;
Expand All @@ -98,6 +100,31 @@ export class SignIn extends BaseResource implements SignInResource {
createdSessionId: string | null = null;
userData: UserData = new UserData(null);

/**
* The current status of the sign-in process.
*
* @returns The current sign-in status, or null if no status has been set
*/
get status(): SignInStatus | null {
return this._status;
}

/**
* Sets the sign-in status and logs the transition at debug level.
*
* @param value - The new status to set. Can be null to clear the status.
* @remarks When setting a new status that differs from the previous one,
* a debug log entry is created showing the transition from the old to new status.
*/
set status(value: SignInStatus | null) {
const previousStatus = this._status;
this._status = value;

if (value && previousStatus !== value) {
debugLogger.debug('SignIn.status', { id: this.id, from: previousStatus, to: value });
}
}

/**
* @experimental This experimental API is subject to change.
*
Expand All @@ -118,7 +145,8 @@ export class SignIn extends BaseResource implements SignInResource {
this.fromJSON(data);
}

create = (params: SignInCreateParams): Promise<this> => {
create = (params: SignInCreateParams): Promise<SignInResource> => {
debugLogger.debug('SignIn.create', { id: this.id, strategy: 'strategy' in params ? params.strategy : undefined });
return this._basePost({
path: this.pathRoot,
body: params,
Expand All @@ -132,76 +160,78 @@ export class SignIn extends BaseResource implements SignInResource {
});
};

prepareFirstFactor = (factor: PrepareFirstFactorParams): Promise<SignInResource> => {
prepareFirstFactor = (params: PrepareFirstFactorParams): Promise<SignInResource> => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed this to params for consistency with other methods and classes

debugLogger.debug('SignIn.prepareFirstFactor', { id: this.id, strategy: params.strategy });
let config;
switch (factor.strategy) {
switch (params.strategy) {
case 'passkey':
config = {} as PassKeyConfig;
break;
case 'email_link':
config = {
emailAddressId: factor.emailAddressId,
redirectUrl: factor.redirectUrl,
emailAddressId: params.emailAddressId,
redirectUrl: params.redirectUrl,
} as EmailLinkConfig;
break;
case 'email_code':
config = { emailAddressId: factor.emailAddressId } as EmailCodeConfig;
config = { emailAddressId: params.emailAddressId } as EmailCodeConfig;
break;
case 'phone_code':
config = {
phoneNumberId: factor.phoneNumberId,
default: factor.default,
channel: factor.channel,
phoneNumberId: params.phoneNumberId,
default: params.default,
channel: params.channel,
} as PhoneCodeConfig;
break;
case 'web3_metamask_signature':
case 'web3_base_signature':
case 'web3_coinbase_wallet_signature':
case 'web3_okx_wallet_signature':
config = { web3WalletId: factor.web3WalletId } as Web3SignatureConfig;
config = { web3WalletId: params.web3WalletId } as Web3SignatureConfig;
break;
case 'reset_password_phone_code':
config = { phoneNumberId: factor.phoneNumberId } as ResetPasswordPhoneCodeFactorConfig;
config = { phoneNumberId: params.phoneNumberId } as ResetPasswordPhoneCodeFactorConfig;
break;
case 'reset_password_email_code':
config = { emailAddressId: factor.emailAddressId } as ResetPasswordEmailCodeFactorConfig;
config = { emailAddressId: params.emailAddressId } as ResetPasswordEmailCodeFactorConfig;
break;
case 'saml':
config = {
redirectUrl: factor.redirectUrl,
actionCompleteRedirectUrl: factor.actionCompleteRedirectUrl,
redirectUrl: params.redirectUrl,
actionCompleteRedirectUrl: params.actionCompleteRedirectUrl,
} as SamlConfig;
break;
case 'enterprise_sso':
config = {
redirectUrl: factor.redirectUrl,
actionCompleteRedirectUrl: factor.actionCompleteRedirectUrl,
oidcPrompt: factor.oidcPrompt,
redirectUrl: params.redirectUrl,
actionCompleteRedirectUrl: params.actionCompleteRedirectUrl,
oidcPrompt: params.oidcPrompt,
} as EnterpriseSSOConfig;
break;
default:
clerkInvalidStrategy('SignIn.prepareFirstFactor', factor.strategy);
clerkInvalidStrategy('SignIn.prepareFirstFactor', params.strategy);
}
return this._basePost({
body: { ...config, strategy: factor.strategy },
body: { ...config, strategy: params.strategy },
action: 'prepare_first_factor',
});
};

attemptFirstFactor = (attemptFactor: AttemptFirstFactorParams): Promise<SignInResource> => {
attemptFirstFactor = (params: AttemptFirstFactorParams): Promise<SignInResource> => {
debugLogger.debug('SignIn.attemptFirstFactor', { id: this.id, strategy: params.strategy });
let config;
switch (attemptFactor.strategy) {
switch (params.strategy) {
case 'passkey':
config = {
publicKeyCredential: JSON.stringify(serializePublicKeyCredentialAssertion(attemptFactor.publicKeyCredential)),
publicKeyCredential: JSON.stringify(serializePublicKeyCredentialAssertion(params.publicKeyCredential)),
};
break;
default:
config = { ...attemptFactor };
config = { ...params };
}

return this._basePost({
body: { ...config, strategy: attemptFactor.strategy },
body: { ...config, strategy: params.strategy },
action: 'attempt_first_factor',
});
};
Expand Down Expand Up @@ -243,13 +273,15 @@ export class SignIn extends BaseResource implements SignInResource {
};

prepareSecondFactor = (params: PrepareSecondFactorParams): Promise<SignInResource> => {
debugLogger.debug('SignIn.prepareSecondFactor', { id: this.id, strategy: params.strategy });
return this._basePost({
body: params,
action: 'prepare_second_factor',
});
};

attemptSecondFactor = (params: AttemptSecondFactorParams): Promise<SignInResource> => {
debugLogger.debug('SignIn.attemptSecondFactor', { id: this.id, strategy: params.strategy });
return this._basePost({
body: params,
action: 'attempt_second_factor',
Expand Down
50 changes: 42 additions & 8 deletions packages/clerk-js/src/core/resources/SignUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import type {
Web3Provider,
} from '@clerk/types';

import { debugLogger } from '@/utils/debug';

import {
generateSignatureWithBase,
generateSignatureWithCoinbaseWallet,
Expand Down Expand Up @@ -70,10 +72,10 @@ export class SignUp extends BaseResource implements SignUpResource {
pathRoot = '/client/sign_ups';

id: string | undefined;
status: SignUpStatus | null = null;
private _status: SignUpStatus | null = null;
requiredFields: SignUpField[] = [];
optionalFields: SignUpField[] = [];
missingFields: SignUpField[] = [];
optionalFields: SignUpField[] = [];
unverifiedFields: SignUpIdentificationField[] = [];
verifications: SignUpVerifications = new SignUpVerifications(null);
username: string | null = null;
Expand All @@ -90,6 +92,31 @@ export class SignUp extends BaseResource implements SignUpResource {
abandonAt: number | null = null;
legalAcceptedAt: number | null = null;

/**
* The current status of the sign-up process.
*
* @returns The current sign-up status, or null if no status has been set
*/
get status(): SignUpStatus | null {
return this._status;
}

/**
* Sets the sign-up status and logs the transition at debug level.
*
* @param value - The new status to set. Can be null to clear the status.
* @remarks When setting a new status that differs from the previous one,
* a debug log entry is created showing the transition from the old to new status.
*/
set status(value: SignUpStatus | null) {
const previousStatus = this._status;
this._status = value;

if (value && previousStatus !== value) {
debugLogger.debug('SignUp.status', { id: this.id, from: previousStatus, to: value });
}
}

/**
* @experimental This experimental API is subject to change.
*
Expand All @@ -110,36 +137,43 @@ export class SignUp extends BaseResource implements SignUpResource {
this.fromJSON(data);
}

create = async (_params: SignUpCreateParams): Promise<SignUpResource> => {
let params: Record<string, unknown> = _params;
create = async (params: SignUpCreateParams): Promise<SignUpResource> => {
debugLogger.debug('SignUp.create', { id: this.id, strategy: params.strategy });

let finalParams = { ...params };

if (!__BUILD_DISABLE_RHC__ && !this.clientBypass() && !this.shouldBypassCaptchaForAttempt(params)) {
const captchaChallenge = new CaptchaChallenge(SignUp.clerk);
const captchaParams = await captchaChallenge.managedOrInvisible({ action: 'signup' });
if (!captchaParams) {
throw new ClerkRuntimeError('', { code: 'captcha_unavailable' });
}
params = { ...params, ...captchaParams };
finalParams = { ...finalParams, ...captchaParams };
}

if (params.transfer && this.shouldBypassCaptchaForAttempt(params)) {
params.strategy = SignUp.clerk.client?.signIn.firstFactorVerification.strategy;
if (finalParams.transfer && this.shouldBypassCaptchaForAttempt(finalParams)) {
const strategy = SignUp.clerk.client?.signIn.firstFactorVerification.strategy;
if (strategy) {
finalParams = { ...finalParams, strategy: strategy as SignUpCreateParams['strategy'] };
}
}

return this._basePost({
path: this.pathRoot,
body: normalizeUnsafeMetadata(params),
body: normalizeUnsafeMetadata(finalParams),
});
};

prepareVerification = (params: PrepareVerificationParams): Promise<this> => {
debugLogger.debug('SignUp.prepareVerification', { id: this.id, strategy: params.strategy });
return this._basePost({
body: params,
action: 'prepare_verification',
});
};

attemptVerification = (params: AttemptVerificationParams): Promise<SignUpResource> => {
debugLogger.debug('SignUp.attemptVerification', { id: this.id, strategy: params.strategy });
return this._basePost({
body: params,
action: 'attempt_verification',
Expand Down
Loading