Skip to content
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

Token isn't being refreshed on expiry #176

Open
pblanchetteNventive opened this issue Jan 21, 2025 · 9 comments
Open

Token isn't being refreshed on expiry #176

pblanchetteNventive opened this issue Jan 21, 2025 · 9 comments
Assignees

Comments

@pblanchetteNventive
Copy link

Bug description

After calling validate(onView:_), the SDK returns a token as expected, but if I wait for the token to expire, the onEvent method is never called.

After some digging inside the SDK It seems that calling validate enables a boolean called resultHandled, which is guarded against when handling further events (HcaptchaWebViewManager: 245)

To Reproduce

  1. start a view with an hcaptcha in invisible mode
  2. call validate to store the token locally
  3. wait the expiry timer
  4. observe that no event is being called by the SDK

Debug Logs

The HCaptcha constructor accepts a diagnosticLog flag (bool) to enable detailed SDK logs. If you would like to report an issue with the SDK, please enable this flag and attach diagnosticLog output when you open the issue.

Expected behavior

The HcaptchaEvent .expired should be called

Logs

2025-01-21 17:50:34.034 main HCaptcha/Debug: WebViewManager.handleResult: log("challenge got token")
2025-01-21 17:50:34.034 main HCaptcha/Debug: WebViewManager.handleResult: log("P1_token")
2025-01-21 17:50:34.034 main HCaptcha/Debug: .stop
2025-01-21 17:50:34.034 main HCaptcha/Debug: WebViewManager.stop
2025-01-21 17:52:34.034 main HCaptcha/Debug: WebViewManager.handleResult: log("expired challenge")
2025-01-21 17:52:34.034 main HCaptcha/Debug: WebViewManager.handleResult skip as handled
2025-01-21 17:52:35.035 main HCaptcha/Debug: WebViewManager.handleResult: error(Response expired and need to re-verify)
2025-01-21 17:52:35.035 main HCaptcha/Debug: WebViewManager.handleResult skip as handled
2025-01-21 17:52:35.035 main HCaptcha/Debug: WebViewManager.handleResult: onExpired
2025-01-21 17:52:35.035 main HCaptcha/Debug: WebViewManager.handleResult skip as handled

Additional context

Writing this makes me wonder If my implementation was done correctly and begs the question, how do you manage to ensure the token is automatically refreshed as specified in the README ?

By default the SDK will automatically fetch a new token upon expiry once you have requested a token via validate. This behavior can be adjusted by passing resetOnError: false to the validate call:

@CAMOBAP
Copy link
Collaborator

CAMOBAP commented Jan 21, 2025

@pblanchetteNventive thanks for the contact

If my implementation was done correctly and begs the question, how do you manage to ensure the token is automatically refreshed as specified in the README ?

It is hard to say without actual code but based on the provided logs I assume that you call stop after receiving the token.

This call prevents us from receiving any future events/errors. If you wanna get expiration callback you should not call stop. Another important note, once you call result.dematerialize, the token considered as 'utilized' so you will not get expiration callback also

@pblanchetteNventive
Copy link
Author

@CAMOBAP this is how I'm configuring the captcha procedure

private func showCaptcha(_ view: UIView) {
        hcaptcha.validate(on: view) { result in
            do {
                token = try result.dematerialize()
                hcaptcha.stop()
                
            } catch {
    
                hcaptcha.reset()
            }
        }
        
        hcaptcha.onEvent { (event, _) in
            switch event {
            case .open:
                self.configureHCaptcha(height: 100, reset: true)
            case .expired:
                self.configureHCaptcha(height: 100, reset: true)
            default:
                break
            }
        }
    } 

showCaptcha(_view:) is called in the onAppear of my view.

This call prevents us from receiving any future events/errors. If you wanna get expiration callback you should not call stop.

You are right I'm calling stop right after

Another important note, once you call result.dematerialize, the token considered as 'utilized' so you will not get expiration callback also

Do you suggest that I store the Hcaptcha result I get from the validate completion handler in my view to keep receiving expiration callback, only to call dematerialize when I'm ready to consume the token ?

@CAMOBAP
Copy link
Collaborator

CAMOBAP commented Jan 22, 2025

Do you suggest that I store the Hcaptcha result I get from the validate completion handler in my view to keep receiving expiration callback, only to call dematerialize when I'm ready to consume the token ?

Yep if you consume/process token not immediately, better to keep result till this moment.

At this moment, the expiration time is 2 minutes. Just to be on the same page: is it possible that you will need the token after 2 minutes?

@pblanchetteNventive
Copy link
Author

At this moment, the expiration time is 2 minutes. Just to be on the same page: is it possible that you will need the token after 2 minutes?

yes, I'm toying with some use cases that require the captcha to be validated at the beginning of some potentially very long form, meaning 2 min is a bit short, and I wanted to rely on the auto-renew feature for that.

Yep if you consume/process token not immediately, better to keep result till this moment.

Can I request that this flow be outlined in the Readme ? I don't think the distinction between validation/dematerialization is outlined in the examples (the swiftUI ones at least)

@CAMOBAP
Copy link
Collaborator

CAMOBAP commented Jan 22, 2025

@pblanchetteNventive make sense, I will update documentation (I will place it in the root README because it affect all cases)

@CAMOBAP
Copy link
Collaborator

CAMOBAP commented Jan 22, 2025

@pblanchetteNventive any feedback appreciated #177

@e271828-
Copy link
Contributor

@pblanchetteNventive Note that if you're an enterprise customer, you can customize the token lifecycle. This would let you just fetch just once, if that pattern makes more sense.

@pblanchetteNventive
Copy link
Author

Maybe it's a bit off topic, but I wanted to avoid spamming issues for a small question:

The way I understand it, the SDK tracks the user behavior trough the app and displays a challenge at relevant key points based on that.

In the case of an app with multiple screens, would it then make sense to init the SDK at the beginning of the app then rather than directly on the page with the challenge ?

@CAMOBAP
Copy link
Collaborator

CAMOBAP commented Jan 27, 2025

In the case of an app with multiple screens, would it then make sense to init the SDK at the beginning of the app then rather than directly on the page with the challenge ?

It makes sense from a performance perspective, the SDK takes some time to init. This is a main consideration for init it ahead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants