-
Notifications
You must be signed in to change notification settings - Fork 390
Create/Update tenant with ReCAPTCHA Config #1586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
1cd6fe5
4bdd00b
f98cd0e
766adc5
930a277
6452fe1
18c2e02
8298b13
9be6dfe
24dad45
bdb0f91
b6bf490
e0c1427
ee241f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1480,6 +1480,54 @@ export interface RecaptchaManagedRule { | |
action?: RecaptchaAction; | ||
} | ||
|
||
export class ManagedRuleAuth implements RecaptchaManagedRule{ | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public readonly endScore: number; | ||
public readonly action: RecaptchaAction; | ||
|
||
public static validate(options: RecaptchaManagedRule): void { | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const validKeys = { | ||
endScore: true, | ||
action: true, | ||
} | ||
if (!validator.isNonNullObject(options)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaManagedRule" must be a non-null object.', | ||
); | ||
} | ||
// Check for unsupported top level attributes. | ||
for (const key in options) { | ||
if (!(key in validKeys)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
`"${key}" is not a valid RecaptchaManagedRule parameter.`, | ||
); | ||
} | ||
} | ||
|
||
// Validate content. | ||
if (typeof options.action !== 'undefined' && | ||
options.action !== 'BLOCK') { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaManagedRule.action" must be "BLOCK".', | ||
); | ||
} | ||
} | ||
|
||
constructor(response: RecaptchaManagedRule) { | ||
if (typeof response.action === 'undefined') { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INTERNAL_ERROR, | ||
'INTERNAL ASSERT FAILED: Invalid provider-reCAPTCHA configuration response'); | ||
} | ||
this.action = response.action; | ||
if (response.endScore !== undefined) { | ||
this.endScore = response.endScore; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* The key's platform type: only web supported now. | ||
*/ | ||
|
@@ -1497,22 +1545,116 @@ export interface RecaptchaKey { | |
/** | ||
* The reCAPTCHA site key. | ||
*/ | ||
key: string; | ||
key: string; | ||
} | ||
|
||
export interface RecaptchaConfig { | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* The enforcement state of email password provider. | ||
*/ | ||
emailPasswordEnforcementState?: RecaptchaProviderEnforcementState; | ||
emailPasswordEnforcementState?: RecaptchaProviderEnforcementState; | ||
lahirumaramba marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* The reCAPTCHA managed rules. | ||
*/ | ||
managedRules: RecaptchaManagedRule[]; | ||
managedRules?: RecaptchaManagedRule[]; | ||
|
||
/** | ||
* The reCAPTCHA keys. | ||
*/ | ||
recaptchaKeys?: RecaptchaKey[]; | ||
recaptchaKeys?: RecaptchaKey[]; | ||
} | ||
|
||
export class RecaptchaAuthConfig implements RecaptchaConfig { | ||
public readonly emailPasswordEnforcementState?: RecaptchaProviderEnforcementState; | ||
public readonly managedRules?: RecaptchaManagedRule[]; | ||
public readonly recaptchaKeys?: RecaptchaKey[]; | ||
|
||
constructor(recaptchaConfig: RecaptchaConfig | undefined) { | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (recaptchaConfig?.emailPasswordEnforcementState !== undefined) { | ||
this.emailPasswordEnforcementState = recaptchaConfig.emailPasswordEnforcementState; | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
if (recaptchaConfig?.managedRules !== undefined) { | ||
this.managedRules = recaptchaConfig.managedRules; | ||
} | ||
if (recaptchaConfig?.recaptchaKeys !== undefined) { | ||
this.recaptchaKeys = recaptchaConfig.recaptchaKeys; | ||
} | ||
} | ||
|
||
public static validate(options: RecaptchaConfig): void { | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const validKeys = { | ||
emailPasswordEnforcementState: true, | ||
managedRules: true, | ||
recaptchaKeys: true, | ||
}; | ||
|
||
if (!validator.isNonNullObject(options)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaConfig" must be a non-null object.', | ||
); | ||
} | ||
|
||
for (const key in options) { | ||
if (!(key in validKeys)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
`"${key}" is not a valid RecaptchaConfig parameter.`, | ||
); | ||
} | ||
} | ||
|
||
// Validation | ||
if (options.emailPasswordEnforcementState !== undefined){ | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (!validator.isNonEmptyString(options.emailPasswordEnforcementState)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_ARGUMENT, | ||
'"RecaptchaConfig.emailPasswordEnforcementState" must be a valid non-empty string.',) | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
if (options.emailPasswordEnforcementState !== 'OFF' && | ||
options.emailPasswordEnforcementState !== 'AUDIT' && | ||
options.emailPasswordEnforcementState !== 'ENFORCE') { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaConfig.emailPasswordEnforcementState" must be either "OFF", "AUDIT" or "ENFORCE".', | ||
); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason for this separation is to align with the backend error-code and keep consistency with the existing error message. E.g. empty string is an INVALID_ARGUMENT but invalid string is an INVALID_CONFIG. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The SDK shouldn't allow empty strings in the request to the BE service so this error technically should not occur (from the backend). I felt like the check is redundant because you check for a restricted set of strings here regardless. Not a big issue so I will leave it up to you to decide the best path here. |
||
|
||
if (typeof options.managedRules !== 'undefined') { | ||
// Validate array | ||
if (!validator.isArray(options.managedRules)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaConfig.managedRules" must be an array of valid "RecaptchaManagedRule".', | ||
); | ||
} | ||
// Validate each rule of the array | ||
options.managedRules.forEach((managedRule) => { | ||
ManagedRuleAuth.validate(managedRule); | ||
}); | ||
lahirumaramba marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
public toJSON(): object { | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const json: any = { | ||
emailPasswordEnforcementState: this.emailPasswordEnforcementState, | ||
managedRules: deepCopy(this.managedRules), | ||
recaptchaKeys: deepCopy(this.recaptchaKeys) | ||
} | ||
|
||
if (typeof json.emailPasswordEnforcementState === 'undefined') { | ||
delete json.emailPasswordEnforcementState; | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
if (typeof json.managedRules === 'undefined') { | ||
delete json.managedRules; | ||
} | ||
if (typeof json.recaptchaKeys === 'undefined') { | ||
delete json.recaptchaKeys; | ||
} | ||
|
||
return json; | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.