feat(passkeys): add CAPTCHA to options endpoint for authentication#2416
feat(passkeys): add CAPTCHA to options endpoint for authentication#2416
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Central YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
492898e to
bff8a56
Compare
4cc4c2c to
83d2b89
Compare
83d2b89 to
8bd82c2
Compare
…ys-captcha-on-auth
ccb8e3d to
b1941a0
Compare
cstockton
left a comment
There was a problem hiding this comment.
Looks good, could push through as is but having the ctx would be ideal.
There was a problem hiding this comment.
Pull request overview
Adds CAPTCHA enforcement to the passkeys authentication options flow and refactors CAPTCHA verification to be dependency-injected for testability.
Changes:
- Introduces a
CaptchaVerifierinterface +HTTPCaptchaVerifierimplementation with configurable timeout. - Injects/verifies CAPTCHA in middleware for
POST /passkeys/authentication/options, with mocks used in API tests. - Adds provider “live” verification tests for hCaptcha and Turnstile.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/security/captcha.go | Refactors CAPTCHA verification into an interface-based HTTP verifier with context support and timeout. |
| internal/security/captcha_test.go | Adds live provider tests for hCaptcha/Turnstile using test tokens/secrets. |
| internal/conf/configuration.go | Extends CAPTCHA config with a Timeout duration field. |
| internal/api/options.go | Adds WithCaptchaVerifier(...) option for DI. |
| internal/api/api.go | Stores/verifies default CAPTCHA verifier on API init; wires verifyCaptcha into passkey auth options route. |
| internal/api/middleware.go | Moves request parsing for captcha token into API middleware and uses injected verifier. |
| internal/api/helpers.go | Updates request param type union to use the new local captchaRequest type. |
| internal/api/captcha_mock_test.go | Introduces a mock verifier for tests. |
| internal/api/middleware_test.go | Switches middleware captcha tests to use the mock verifier instead of live providers. |
| internal/api/passkey_test.go | Injects mock captcha verifier into passkey test suite and resets its state per test. |
| internal/api/passkey_authentication_test.go | Adds passkey auth options tests covering captcha required/valid/invalid/disabled scenarios. |
Comments suppressed due to low confidence (2)
internal/api/middleware.go:248
a.captchaVerifier.Verify(...)can legally return(nil, nil)(e.g., a buggy/mock implementation). In that caseverificationResult.Successwill panic. Consider guarding against a nilverificationResultand treating it as an internal error (or a failed verification) to keep the middleware robust.
verificationResult, err := a.captchaVerifier.Verify(
ctx,
token,
utilities.GetIPAddress(req),
)
if err != nil {
return nil, apierrors.NewInternalServerError("captcha verification process failed").WithInternalError(err)
}
if !verificationResult.Success {
return nil, apierrors.NewBadRequestError(apierrors.ErrorCodeCaptchaFailed, "captcha protection: request disallowed (%s)", strings.Join(verificationResult.ErrorCodes, ", "))
}
internal/conf/configuration.go:733
CaptchaConfiguration.Timeoutis user-configurable butValidate()doesn’t sanity-check it. A negative duration (or extremely low timeout) could cause immediate failures or surprising behavior. Consider validatingTimeout >= 0(and possibly enforcing a sensible minimum) when CAPTCHA is enabled.
type CaptchaConfiguration struct {
Enabled bool `json:"enabled" default:"false"`
Provider string `json:"provider" default:"hcaptcha"`
Secret string `json:"provider_secret"`
Timeout time.Duration `json:"timeout" split_words:"true" default:"10s"`
}
func (c *CaptchaConfiguration) Validate() error {
if !c.Enabled {
return nil
}
if c.Provider != "hcaptcha" && c.Provider != "turnstile" {
return fmt.Errorf("unsupported captcha provider: %s", c.Provider)
}
c.Secret = strings.TrimSpace(c.Secret)
if c.Secret == "" {
return errors.New("captcha provider secret is empty")
}
return nil
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ys-captcha-on-auth
/passkeys/authentication/optionsendpoint.