@@ -1750,6 +1750,21 @@ export interface RecaptchaManagedRule {
17501750 action ?: RecaptchaAction ;
17511751}
17521752
1753+ /**
1754+ * The managed rules for toll fraud provider, containing the enforcement status.
1755+ * The toll fraud provider contains all SMS related user flows.
1756+ */
1757+ export interface RecaptchaTollFraudManagedRule {
1758+ /**
1759+ * The action will be enforced if the reCAPTCHA score of a request is larger than startScore.
1760+ */
1761+ startScore : number ;
1762+ /**
1763+ * The action for reCAPTCHA-protected requests.
1764+ */
1765+ action ?: RecaptchaAction ;
1766+ }
1767+
17531768/**
17541769 * The key's platform type.
17551770 */
@@ -1781,34 +1796,131 @@ export interface RecaptchaConfig {
17811796 * The enforcement state of the email password provider.
17821797 */
17831798 emailPasswordEnforcementState ?: RecaptchaProviderEnforcementState ;
1799+ /**
1800+ * The enforcement state of the phone provider.
1801+ */
1802+ phoneEnforcementState ?: RecaptchaProviderEnforcementState ;
17841803 /**
17851804 * The reCAPTCHA managed rules.
17861805 */
17871806 managedRules ?: RecaptchaManagedRule [ ] ;
1788-
17891807 /**
17901808 * The reCAPTCHA keys.
17911809 */
17921810 recaptchaKeys ?: RecaptchaKey [ ] ;
1793-
17941811 /**
17951812 * Whether to use account defender for reCAPTCHA assessment.
17961813 * The default value is false.
17971814 */
17981815 useAccountDefender ?: boolean ;
1816+ /**
1817+ * Whether to use the rCE bot score for reCAPTCHA phone provider.
1818+ * Can only be true when the phone_enforcement_state is AUDIT or ENFORCE.
1819+ */
1820+ useSmsBotScore ?: boolean ;
1821+ /**
1822+ * Whether to use the rCE SMS toll fraud protection risk score for reCAPTCHA phone provider.
1823+ * Can only be true when the phone_enforcement_state is AUDIT or ENFORCE.
1824+ */
1825+ useSmsTollFraudProtection ?: boolean ;
1826+ /**
1827+ * The managed rules for toll fraud provider, containing the enforcement status.
1828+ * The toll fraud provider contains all SMS related user flows.
1829+ */
1830+ smsTollFraudManagedRules ?: RecaptchaTollFraudManagedRule [ ] ;
1831+ }
1832+
1833+ /**
1834+ * Server side recaptcha configuration.
1835+ */
1836+ export interface RecaptchaAuthServerConfig {
1837+ emailPasswordEnforcementState ?: RecaptchaProviderEnforcementState ;
1838+ phoneEnforcementState ?: RecaptchaProviderEnforcementState ;
1839+ managedRules ?: RecaptchaManagedRule [ ] ;
1840+ recaptchaKeys ?: RecaptchaKey [ ] ;
1841+ useAccountDefender ?: boolean ;
1842+ useSmsBotScore ?: boolean ;
1843+ useSmsTollFraudProtection ?: boolean ;
1844+ tollFraudManagedRules ?: RecaptchaTollFraudManagedRule [ ] ;
17991845}
18001846
1847+ /**
1848+ * Defines the recaptcha config class used to convert client side RecaptchaConfig
1849+ * to a format that is understood by the Auth server.
1850+ *
1851+ * @internal
1852+ */
18011853export class RecaptchaAuthConfig implements RecaptchaConfig {
18021854 public readonly emailPasswordEnforcementState ?: RecaptchaProviderEnforcementState ;
1855+ public readonly phoneEnforcementState ?: RecaptchaProviderEnforcementState ;
18031856 public readonly managedRules ?: RecaptchaManagedRule [ ] ;
18041857 public readonly recaptchaKeys ?: RecaptchaKey [ ] ;
18051858 public readonly useAccountDefender ?: boolean ;
1859+ public readonly useSmsBotScore ?: boolean ;
1860+ public readonly useSmsTollFraudProtection ?: boolean ;
1861+ public readonly smsTollFraudManagedRules ?: RecaptchaTollFraudManagedRule [ ] ;
1862+
1863+
1864+ /**
1865+ * The RecaptchaAuthConfig constructor.
1866+ *
1867+ * @param response - The server side response used to initialize the
1868+ * RecaptchaAuthConfig object.
1869+ * @constructor
1870+ * @internal
1871+ */
1872+ constructor ( response : RecaptchaAuthServerConfig ) {
1873+ const filteredResponse = Object . fromEntries (
1874+ Object . entries ( response ) . filter ( ( [ , value ] ) => value !== undefined )
1875+ ) ;
1876+
1877+ // Explicitly map the 'tollFraudManagedRules' to 'smsTollFraudManagedRules'
1878+ if ( filteredResponse . tollFraudManagedRules !== undefined ) {
1879+ this . smsTollFraudManagedRules = filteredResponse . tollFraudManagedRules ;
1880+ delete filteredResponse . tollFraudManagedRules ; // Remove it if necessary
1881+ }
1882+
1883+ // Assign the remaining properties directly
1884+ Object . assign ( this , filteredResponse ) ;
1885+ }
1886+
1887+ /**
1888+ * Builds a server request object from the client-side RecaptchaConfig.
1889+ * Converts client-side fields to their server-side equivalents.
1890+ *
1891+ * @param options - The client-side RecaptchaConfig object.
1892+ * @returns The server-side RecaptchaAuthServerConfig object.
1893+ */
1894+ public static buildServerRequest ( options : RecaptchaConfig ) : RecaptchaAuthServerConfig {
1895+ RecaptchaAuthConfig . validate ( options ) ; // Validate options before building request
1896+
1897+ const request : RecaptchaAuthServerConfig = { } ;
18061898
1807- constructor ( recaptchaConfig : RecaptchaConfig ) {
1808- this . emailPasswordEnforcementState = recaptchaConfig . emailPasswordEnforcementState ;
1809- this . managedRules = recaptchaConfig . managedRules ;
1810- this . recaptchaKeys = recaptchaConfig . recaptchaKeys ;
1811- this . useAccountDefender = recaptchaConfig . useAccountDefender ;
1899+ if ( typeof options . emailPasswordEnforcementState !== 'undefined' ) {
1900+ request . emailPasswordEnforcementState = options . emailPasswordEnforcementState ;
1901+ }
1902+ if ( typeof options . phoneEnforcementState !== 'undefined' ) {
1903+ request . phoneEnforcementState = options . phoneEnforcementState ;
1904+ }
1905+ if ( typeof options . managedRules !== 'undefined' ) {
1906+ request . managedRules = options . managedRules ;
1907+ }
1908+ if ( typeof options . recaptchaKeys !== 'undefined' ) {
1909+ request . recaptchaKeys = options . recaptchaKeys ;
1910+ }
1911+ if ( typeof options . useAccountDefender !== 'undefined' ) {
1912+ request . useAccountDefender = options . useAccountDefender ;
1913+ }
1914+ if ( typeof options . useSmsBotScore !== 'undefined' ) {
1915+ request . useSmsBotScore = options . useSmsBotScore ;
1916+ }
1917+ if ( typeof options . useSmsTollFraudProtection !== 'undefined' ) {
1918+ request . useSmsTollFraudProtection = options . useSmsTollFraudProtection ;
1919+ }
1920+ if ( typeof options . smsTollFraudManagedRules !== 'undefined' ) {
1921+ request . tollFraudManagedRules = options . smsTollFraudManagedRules ; // Map client-side field to server-side
1922+ }
1923+ return request ;
18121924 }
18131925
18141926 /**
@@ -1818,9 +1930,13 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
18181930 public static validate ( options : RecaptchaConfig ) : void {
18191931 const validKeys = {
18201932 emailPasswordEnforcementState : true ,
1933+ phoneEnforcementState : true ,
18211934 managedRules : true ,
18221935 recaptchaKeys : true ,
18231936 useAccountDefender : true ,
1937+ useSmsBotScore : true ,
1938+ useSmsTollFraudProtection : true ,
1939+ smsTollFraudManagedRules : true ,
18241940 } ;
18251941
18261942 if ( ! validator . isNonNullObject ( options ) ) {
@@ -1840,7 +1956,7 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
18401956 }
18411957
18421958 // Validation
1843- if ( typeof options . emailPasswordEnforcementState !== undefined ) {
1959+ if ( typeof options . emailPasswordEnforcementState !== ' undefined' ) {
18441960 if ( ! validator . isNonEmptyString ( options . emailPasswordEnforcementState ) ) {
18451961 throw new FirebaseAuthError (
18461962 AuthClientErrorCode . INVALID_ARGUMENT ,
@@ -1858,6 +1974,24 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
18581974 }
18591975 }
18601976
1977+ if ( typeof options . phoneEnforcementState !== 'undefined' ) {
1978+ if ( ! validator . isNonEmptyString ( options . phoneEnforcementState ) ) {
1979+ throw new FirebaseAuthError (
1980+ AuthClientErrorCode . INVALID_ARGUMENT ,
1981+ '"RecaptchaConfig.phoneEnforcementState" must be a valid non-empty string.' ,
1982+ ) ;
1983+ }
1984+
1985+ if ( options . phoneEnforcementState !== 'OFF' &&
1986+ options . phoneEnforcementState !== 'AUDIT' &&
1987+ options . phoneEnforcementState !== 'ENFORCE' ) {
1988+ throw new FirebaseAuthError (
1989+ AuthClientErrorCode . INVALID_CONFIG ,
1990+ '"RecaptchaConfig.phoneEnforcementState" must be either "OFF", "AUDIT" or "ENFORCE".' ,
1991+ ) ;
1992+ }
1993+ }
1994+
18611995 if ( typeof options . managedRules !== 'undefined' ) {
18621996 // Validate array
18631997 if ( ! validator . isArray ( options . managedRules ) ) {
@@ -1880,6 +2014,38 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
18802014 ) ;
18812015 }
18822016 }
2017+
2018+ if ( typeof options . useSmsBotScore !== 'undefined' ) {
2019+ if ( ! validator . isBoolean ( options . useSmsBotScore ) ) {
2020+ throw new FirebaseAuthError (
2021+ AuthClientErrorCode . INVALID_CONFIG ,
2022+ '"RecaptchaConfig.useSmsBotScore" must be a boolean value".' ,
2023+ ) ;
2024+ }
2025+ }
2026+
2027+ if ( typeof options . useSmsTollFraudProtection !== 'undefined' ) {
2028+ if ( ! validator . isBoolean ( options . useSmsTollFraudProtection ) ) {
2029+ throw new FirebaseAuthError (
2030+ AuthClientErrorCode . INVALID_CONFIG ,
2031+ '"RecaptchaConfig.useSmsTollFraudProtection" must be a boolean value".' ,
2032+ ) ;
2033+ }
2034+ }
2035+
2036+ if ( typeof options . smsTollFraudManagedRules !== 'undefined' ) {
2037+ // Validate array
2038+ if ( ! validator . isArray ( options . smsTollFraudManagedRules ) ) {
2039+ throw new FirebaseAuthError (
2040+ AuthClientErrorCode . INVALID_CONFIG ,
2041+ '"RecaptchaConfig.smsTollFraudManagedRules" must be an array of valid "RecaptchaTollFraudManagedRule".' ,
2042+ ) ;
2043+ }
2044+ // Validate each rule of the array
2045+ options . smsTollFraudManagedRules . forEach ( ( tollFraudManagedRule ) => {
2046+ RecaptchaAuthConfig . validateTollFraudManagedRule ( tollFraudManagedRule ) ;
2047+ } ) ;
2048+ }
18832049 }
18842050
18852051 /**
@@ -1918,32 +2084,38 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
19182084 }
19192085
19202086 /**
1921- * Returns a JSON-serializable representation of this object.
1922- * @returns The JSON-serializable object representation of the ReCaptcha config instance
2087+ * Validate each element in TollFraudManagedRule array
2088+ * @param options - The options object to validate.
19232089 */
1924- public toJSON ( ) : object {
1925- const json : any = {
1926- emailPasswordEnforcementState : this . emailPasswordEnforcementState ,
1927- managedRules : deepCopy ( this . managedRules ) ,
1928- recaptchaKeys : deepCopy ( this . recaptchaKeys ) ,
1929- useAccountDefender : this . useAccountDefender ,
1930- }
1931-
1932- if ( typeof json . emailPasswordEnforcementState === 'undefined' ) {
1933- delete json . emailPasswordEnforcementState ;
2090+ private static validateTollFraudManagedRule ( options : RecaptchaTollFraudManagedRule ) : void {
2091+ const validKeys = {
2092+ startScore : true ,
2093+ action : true ,
19342094 }
1935- if ( typeof json . managedRules === 'undefined' ) {
1936- delete json . managedRules ;
2095+ if ( ! validator . isNonNullObject ( options ) ) {
2096+ throw new FirebaseAuthError (
2097+ AuthClientErrorCode . INVALID_CONFIG ,
2098+ '"RecaptchaTollFraudManagedRule" must be a non-null object.' ,
2099+ ) ;
19372100 }
1938- if ( typeof json . recaptchaKeys === 'undefined' ) {
1939- delete json . recaptchaKeys ;
2101+ // Check for unsupported top level attributes.
2102+ for ( const key in options ) {
2103+ if ( ! ( key in validKeys ) ) {
2104+ throw new FirebaseAuthError (
2105+ AuthClientErrorCode . INVALID_CONFIG ,
2106+ `"${ key } " is not a valid RecaptchaTollFraudManagedRule parameter.` ,
2107+ ) ;
2108+ }
19402109 }
19412110
1942- if ( typeof json . useAccountDefender === 'undefined' ) {
1943- delete json . useAccountDefender ;
2111+ // Validate content.
2112+ if ( typeof options . action !== 'undefined' &&
2113+ options . action !== 'BLOCK' ) {
2114+ throw new FirebaseAuthError (
2115+ AuthClientErrorCode . INVALID_CONFIG ,
2116+ '"RecaptchaTollFraudManagedRule.action" must be "BLOCK".' ,
2117+ ) ;
19442118 }
1945-
1946- return json ;
19472119 }
19482120}
19492121
0 commit comments