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

turnstile #2749

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open

Conversation

gocoffeecup
Copy link
Contributor

@gocoffeecup gocoffeecup commented Dec 4, 2023

🤖[deprecated] Generated by Copilot at 38d2d19

Implemented a turnstile feature for the API using Cloudflare's API and a custom middleware. The feature is used to limit the access to the explorer during periods of high load by requiring the client to pass a captcha challenge. The feature can be enabled or disabled by configuration options and applied to any handler that needs the turnstile mechanism. The feature also involves changes to the client side scripts and templates to use the turnstile token and widget.

Copy link
Collaborator

@manuelsc manuelsc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple suggestions and a few issues I stumbled upon. I hope my screenshots can help debug these issues. Let me know if you need further info

router.HandleFunc("/slot/{slot}/attestations", handlers.SlotAttestationsData).Methods("GET")
router.HandleFunc("/slot/{slot}/withdrawals", handlers.SlotWithdrawalData).Methods("GET")
router.HandleFunc("/slot/{slot}/blsChange", handlers.SlotBlsChangeData).Methods("GET")
router.HandleFunc("/slot/{slotOrHash}/deposits", utils.Adapt(http.HandlerFunc(handlers.SlotDepositData), utils.TurnstileMiddleware).ServeHTTP).Methods("GET")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if you are aware but you can also do middlewares pretty easily by defining a subroute. You can eliminate redundant parts that way. Or was this a deliberate choice doing it that way?

turnstileRouter := router.PathPrefix("/").Subrouter()
turnstileRouter.HandleFunc("/slot/{slotOrHash}/deposits"", handlers.SlotDepositData).Methods("GET")
....
turnstileRouter.Use(utils.TurnstileMiddleware)


validuntil := time.Now().Add(time.Duration(utils.Config.Frontend.Turnstile.SessionMaxAge) * time.Second).Format(time.RFC3339)

utils.SessionStore.SCS.Put(r.Context(), "TURNSTILE::VALIDUNTIL", validuntil)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Store current timestamp in SessionStore and in the verify function check if timestamp + SessionMaxAge > now. That way we can adjust the window how long it is valid whenever we want or a some point even dynamically based on the load.

}

if err != nil {
fmt.Println(err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use utils.LogError

return fmt.Errorf("error decoding turnstile response: %w", err)
}

fmt.Print(r)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debug output

// clear cookie
cookie.MaxAge = -1
http.SetCookie(w, &cookie)
http.Error(w, "Turnstile challenge failed", http.StatusServiceUnavailable)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on the error you might want to return a different status code. For example if the challenge was not successful, you return a specific error but returning service unavailable is not correct, something like Bad Request would be better suited.


validuntil := time.Now().Add(time.Duration(utils.Config.Frontend.Turnstile.SessionMaxAge) * time.Second).Format(time.RFC3339)

utils.SessionStore.SCS.Put(r.Context(), "TURNSTILE::VALIDUNTIL", validuntil)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not store and retrieve it as an int64, no need to format it

utils/utils.go Outdated
func TurnstileMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

cookie := http.Cookie{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: It's a bit confusing, above you define the cookie with MaxAge and set MaxAge = -1 when you clear it and here MagAge -1 is default. Maybe to improve readability moving this to functions is a better idea. Something like SetTurnstileVerifiedCookie and clearTurnstileVerifiedCookie. What do you think?

@@ -377,102 +377,103 @@ func main() {
)

router.HandleFunc("/", handlers.Index).Methods("GET")
router.HandleFunc("/latestState", handlers.LatestState).Methods("GET")
router.HandleFunc("/launchMetrics", handlers.SlotVizMetrics).Methods("GET")
router.HandleFunc("/turnstile/verify", handlers.VerifyTurnstile).Methods("GET")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
image

Modal appeared twice and I had to click "I am humand" twice. Hope this screenshots of my network traffic helps. I was on the index page.

Edit: Now the modal even appear three times

@@ -377,102 +377,103 @@ func main() {
)

router.HandleFunc("/", handlers.Index).Methods("GET")
router.HandleFunc("/latestState", handlers.LatestState).Methods("GET")
router.HandleFunc("/launchMetrics", handlers.SlotVizMetrics).Methods("GET")
router.HandleFunc("/turnstile/verify", handlers.VerifyTurnstile).Methods("GET")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I'm getting a couple errors on the index page when I'm on your branch. Clicked I am human and these errors are piling up, they do not appear on the master branch:
image
You can ignore the ads errors, probably due to adblock.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think my branch was behind, I merged the current master and this seems to be resolved now

@@ -7,6 +7,17 @@ var subsTable = null
// let validators = []

function create_typeahead(input_container) {
function prepare(query, settings) {
settings.url = settings.url.replace("%QUERY", encodeURIComponent(query))
settings.beforeSend = function (jqXHR) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code snippet appears on multiple locations. Maybe make it a function that wraps this, like you did with waitForTurnstileToken

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

Successfully merging this pull request may close these issues.

None yet

2 participants