@@ -1750,6 +1750,21 @@ export interface RecaptchaManagedRule {
1750
1750
action ?: RecaptchaAction ;
1751
1751
}
1752
1752
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
+
1753
1768
/**
1754
1769
* The key's platform type.
1755
1770
*/
@@ -1781,34 +1796,131 @@ export interface RecaptchaConfig {
1781
1796
* The enforcement state of the email password provider.
1782
1797
*/
1783
1798
emailPasswordEnforcementState ?: RecaptchaProviderEnforcementState ;
1799
+ /**
1800
+ * The enforcement state of the phone provider.
1801
+ */
1802
+ phoneEnforcementState ?: RecaptchaProviderEnforcementState ;
1784
1803
/**
1785
1804
* The reCAPTCHA managed rules.
1786
1805
*/
1787
1806
managedRules ?: RecaptchaManagedRule [ ] ;
1788
-
1789
1807
/**
1790
1808
* The reCAPTCHA keys.
1791
1809
*/
1792
1810
recaptchaKeys ?: RecaptchaKey [ ] ;
1793
-
1794
1811
/**
1795
1812
* Whether to use account defender for reCAPTCHA assessment.
1796
1813
* The default value is false.
1797
1814
*/
1798
1815
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 [ ] ;
1799
1845
}
1800
1846
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
+ */
1801
1853
export class RecaptchaAuthConfig implements RecaptchaConfig {
1802
1854
public readonly emailPasswordEnforcementState ?: RecaptchaProviderEnforcementState ;
1855
+ public readonly phoneEnforcementState ?: RecaptchaProviderEnforcementState ;
1803
1856
public readonly managedRules ?: RecaptchaManagedRule [ ] ;
1804
1857
public readonly recaptchaKeys ?: RecaptchaKey [ ] ;
1805
1858
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 = { } ;
1806
1898
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 ;
1812
1924
}
1813
1925
1814
1926
/**
@@ -1818,9 +1930,13 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
1818
1930
public static validate ( options : RecaptchaConfig ) : void {
1819
1931
const validKeys = {
1820
1932
emailPasswordEnforcementState : true ,
1933
+ phoneEnforcementState : true ,
1821
1934
managedRules : true ,
1822
1935
recaptchaKeys : true ,
1823
1936
useAccountDefender : true ,
1937
+ useSmsBotScore : true ,
1938
+ useSmsTollFraudProtection : true ,
1939
+ smsTollFraudManagedRules : true ,
1824
1940
} ;
1825
1941
1826
1942
if ( ! validator . isNonNullObject ( options ) ) {
@@ -1840,7 +1956,7 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
1840
1956
}
1841
1957
1842
1958
// Validation
1843
- if ( typeof options . emailPasswordEnforcementState !== undefined ) {
1959
+ if ( typeof options . emailPasswordEnforcementState !== ' undefined' ) {
1844
1960
if ( ! validator . isNonEmptyString ( options . emailPasswordEnforcementState ) ) {
1845
1961
throw new FirebaseAuthError (
1846
1962
AuthClientErrorCode . INVALID_ARGUMENT ,
@@ -1858,6 +1974,24 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
1858
1974
}
1859
1975
}
1860
1976
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
+
1861
1995
if ( typeof options . managedRules !== 'undefined' ) {
1862
1996
// Validate array
1863
1997
if ( ! validator . isArray ( options . managedRules ) ) {
@@ -1880,6 +2014,38 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
1880
2014
) ;
1881
2015
}
1882
2016
}
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
+ }
1883
2049
}
1884
2050
1885
2051
/**
@@ -1918,32 +2084,38 @@ export class RecaptchaAuthConfig implements RecaptchaConfig {
1918
2084
}
1919
2085
1920
2086
/**
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.
1923
2089
*/
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 ,
1934
2094
}
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
+ ) ;
1937
2100
}
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
+ }
1940
2109
}
1941
2110
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
+ ) ;
1944
2118
}
1945
-
1946
- return json ;
1947
2119
}
1948
2120
}
1949
2121
0 commit comments