OpenWAF Verify open sourceNew

The browser side of OpenWAF Verify, its protocol and its siteverify libraries are open source under Apache-2.0. What is open, what is not, and why.

On this page

The client side of OpenWAF Verify is open source under the Apache License 2.0: github.com/openwaf-dev/verify (external link). That is the code that runs in your visitors' browsers, the protocol it speaks with the edge, and the libraries your server uses to check tokens.

You can read what the Verify widget and the browser challenge do in a visitor's browser, check it against what your site serves, and use the libraries instead of writing your own siteverify calls.

What is open

  • Browser widget (challengejs/). The widget.js script: the box, its states, the owafVerify API and the hidden owaf-verify-response field.
  • Proof-of-work worker (challengejs/). The Web Worker that solves the SHA-256 puzzles, and the fallback that runs on the page without a worker.
  • Interstitial page (challengejs/). The HTML template and CSS of the browser challenge page.
  • Protocol (spec/). How the browser gets a challenge, sends its solution and receives a token, and the siteverify API.
  • Siteverify libraries. Go (siteverify/, module github.com/openwaf-dev/verify), Node.js and TypeScript (node/, @openwaf/verify) and PHP (php/, Composer package openwaf/verify).
  • Components. React (react/, @openwaf/verify-react) and Vue 3 (vue/, @openwaf/verify-vue).
  • Examples (examples/). Small working apps that render the widget and check the token.

What is not open, and why

Some parts stay closed:

  • Risk scoring. How the edge turns server-side signals into a score.
  • The browser-consistency rule. How the edge checks that a browser behaves like the browser it says it is.
  • The in-page automation checks. The module of yes/no checks about automation tools, and how its answer is encoded for each challenge.
  • Reputation and threat feeds. The lists and sources behind threat feeds and reputation.
  • Edge internals. The proxy and how its nodes work.

These parts decide how hard the edge looks at a request. If their exact rules were public, automation could be tuned to pass them, and each one would stop working on the day it was published.

What they read is not secret. The data each part processes is listed in Data processed and in risk scoring.

The served widget is not byte-identical

The widget your edge serves is this open code plus one closed extension module: the in-page automation checks.

  • The module runs a few yes/no checks in the page.
  • Its only output is one opaque integer, added to the solve request.
  • It reads no fingerprinting surface: no canvas, WebGL, audio, fonts or high-entropy client hints.

Because of that module, a build from the repository is not byte-identical to the bundle at /__waf/challenge/v1/widget.js. Everything else in that bundle is the code in challengejs/.

Check it yourself

You don't have to take our word for it. Open a page that uses Verify, such as the live demo, with your browser's developer tools:

  1. Network. Every request the widget makes goes to the page's own host, under /__waf/. Nothing goes to another domain.
  2. Cookies. The widget sets no cookie. The browser challenge page sets only __waf_pass, after a successful solve.
  3. Content Security Policy. The widget works with Content-Security-Policy: default-src 'self', with no violations in the console. The demo runs under that policy.
  4. Source. Read the served widget.js and worker.js and compare them with challengejs/ in the repository.

Use the libraries

The libraries call siteverify for you. They follow the siteverify reference and behave the same in every language. For now they install from the GitHub repository: Go and Composer from the v0.1.0 tag, npm from the tarballs attached to the release (external link). The npm and Packagist packages are coming soon.

go get github.com/openwaf-dev/verify/siteverify@v0.1.0
signup.go
c, err := siteverify.New(os.Getenv("OWAF_VERIFY_SECRET"))
if err != nil {
	log.Fatal(err)
}

res, err := c.Verify(r.Context(), r.FormValue("owaf-verify-response"), siteverify.Params{
	RemoteIP:       clientIP,
	ExpectedAction: "signup",
})
if err != nil || !res.Success {
	http.Error(w, "verification failed", http.StatusForbidden)
	return
}
// create the account

The React and Vue components render the same widget, so the page must be served through OpenWAF.

What the server libraries do:

  • Defaults. They call https://dash.openwaf.dev/v1/challenge/siteverify with a 10-second timeout. You can point them at https://<your host>/__waf/challenge/siteverify instead.
  • No request when it can't succeed. An empty token returns missing-input-response and a token longer than 2048 bytes returns invalid-input-response, without calling siteverify.
  • Host name and action. When you pass an expected host name or action and the token doesn't match, the answer is a failure with hostname-mismatch or action-mismatch. These two codes come from the library, not from siteverify.
  • Answers and errors. Every siteverify answer, including 400, 405 and 429 (with its Retry-After), comes back as a result. A timeout, a network failure, another HTTP status or a body that isn't JSON is an error: sentinel errors in Go, SiteverifyError in Node and SiteverifyException in PHP, with the codes timeout, network, http and bad-response.
  • No automatic retries. To retry after a timeout, send the same idempotency key again: the second call gets the first answer instead of timeout-or-duplicate.
  • The secret stays out of errors. It never appears in error messages, logs or printed objects.

Try them with the test keys: ows_test_pass, ows_test_fail and ows_test_spent work without a widget.

Licence

Everything in the repository is under the Apache License 2.0 (external link). You can use, change and redistribute it, including in commercial products.

Contribute

Open issues and pull requests at github.com/openwaf-dev/verify (external link). We review every change. Changes to the browser code are released with the edge, so a merged change reaches sites with the next edge release.

Report a vulnerability

Don't open a public issue. Write to support@openwaf.dev (security@openwaf.dev reaches the same team) and follow the repository's SECURITY.md (external link).

Last updated:

↑↓ to navigate↵ to openesc to close