diff --git a/src/lib/errors.ts b/src/lib/errors.ts index 7fe8561d2..5c1352268 100644 --- a/src/lib/errors.ts +++ b/src/lib/errors.ts @@ -124,3 +124,25 @@ export class AuthRetryableFetchError extends CustomAuthError { export function isAuthRetryableFetchError(error: unknown): error is AuthRetryableFetchError { return isAuthError(error) && error.name === 'AuthRetryableFetchError' } + +/** + * This error is thrown on certain methods when the password used is deemed + * weak. Inspect the reasons to identify what password strength rules are + * inadequate. + */ +export class AuthWeakPasswordError extends CustomAuthError { + /** + * Reasons why the password is deemed weak. + */ + reasons: ('length' | 'characters' | 'pwned' | string)[] + + constructor(message: string, status: number, reasons: string[]) { + super(message, 'AuthWeakPasswordError', status) + + this.reasons = reasons + } +} + +export function isAuthWeakPasswordError(error: unknown): error is AuthWeakPasswordError { + return isAuthError(error) && error.name === 'AuthWeakPasswordError' +} diff --git a/src/lib/fetch.ts b/src/lib/fetch.ts index 3ccfe589e..359179d0f 100644 --- a/src/lib/fetch.ts +++ b/src/lib/fetch.ts @@ -7,7 +7,12 @@ import { User, UserResponse, } from './types' -import { AuthApiError, AuthRetryableFetchError, AuthUnknownError } from './errors' +import { + AuthApiError, + AuthRetryableFetchError, + AuthWeakPasswordError, + AuthUnknownError, +} from './errors' export type Fetch = typeof fetch @@ -46,6 +51,22 @@ async function handleError(error: unknown) { throw new AuthUnknownError(_getErrorMessage(e), e) } + if ( + typeof data === 'object' && + data && + typeof data.weak_password === 'object' && + data.weak_password && + Array.isArray(data.weak_password.reasons) && + data.weak_password.reasons.length && + data.weak_password.reduce((a: boolean, i: any) => a && typeof i === 'string', true) + ) { + throw new AuthWeakPasswordError( + _getErrorMessage(data), + error.status, + data.weak_password.reasons + ) + } + throw new AuthApiError(_getErrorMessage(data), error.status || 500) } diff --git a/src/lib/helpers.ts b/src/lib/helpers.ts index 1469f96e6..16c3ebce6 100644 --- a/src/lib/helpers.ts +++ b/src/lib/helpers.ts @@ -290,8 +290,11 @@ function base64urlencode(str: string) { } export async function generatePKCEChallenge(verifier: string) { - const hasCryptoSupport = typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined' && typeof TextEncoder !== 'undefined'; - + const hasCryptoSupport = + typeof crypto !== 'undefined' && + typeof crypto.subtle !== 'undefined' && + typeof TextEncoder !== 'undefined' + if (!hasCryptoSupport) { console.warn( 'WebCrypto API is not supported. Code challenge method will default to use plain instead of sha256.'