Skip to content

Repository files navigation

WebAuthn Proxy

A standalone reverse-proxy for passwordless Webauthn authentication. Supports hardware authenticators like Yubikey, Touch ID etc.

Login Registration
WebAuthn Proxy Login Page WebAuthn Proxy Registration

Quick Start

Using Docker (Recommended)

# Run the proxy
docker run --rm -ti -p 8080:8080 quiq/webauthn_proxy:latest

# With custom config
docker run --rm -ti -p 8080:8080 -v /path/to/config:/opt/config:ro quiq/webauthn_proxy:latest

# Generate cookie secret for credentials.yml
docker run --rm --log-driver=none quiq/webauthn_proxy:latest -generate-secret

Using Go

# Run directly
go run .

# Build
go build -o webauthn_proxy . && chmod +x webauthn_proxy
./webauthn_proxy -v

Setup

  1. Configuration: Create config/config.yml with your settings (see Configuration). rpOrigins is required, the proxy will not start without it.

  2. Credentials: Create your credentials file from the example:

    cp config/credentials.yml.example config/credentials.yml

    config/credentials.yml is git-ignored, as it holds your cookie secrets and user credentials.

  3. Register: Visit http://localhost:8080/webauthn/register

  4. Add User: Copy the generated credential to credentials.yml and restart

  5. Login: Visit http://localhost:8080/webauthn/login

Configuration

Required Options

rpDisplayName: "MyCompany"          # Your organization name
rpID: "example.com"                 # Your domain
rpOrigins:                          # Allow-list of origins used to reach the proxy
  - "https://service.example.com"

rpOrigins is a strict allow-list and has no default. Requests whose origin is not listed are rejected, so the Host header cannot be used to spoof an origin. The proxy refuses to start if the list is empty.

Common Options

  • serverAddress: Listen address (default: 0.0.0.0)
  • serverPort: Listen port (default: 8080)
  • testMode: Allow immediate login after registration (default: false)
  • cookieSecure: Set the Secure flag on cookies (default: true, disable only for local plain HTTP testing)
  • sessionSoftTimeoutSeconds: Session timeout (default: 28800 / 8 hours)

Full configuration options

Integration

NGinx

location / {
    auth_request /webauthn/auth;
    error_page 401 = /webauthn/login?redirect_url=$uri;
    # ...
}

location /webauthn/ {
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;
    proxy_pass http://127.0.0.1:8080;
}

OpenResty (with OAuth2 Proxy)

location / {
    auth_request /oauth2/auth;
    auth_request_set $email $upstream_http_x_auth_request_email;
    error_page 401 = /oauth2/start?rd=$uri;
    access_by_lua_block {
        local http = require "resty.http"
        local h = http.new()
        h:set_timeout(5 * 1000)
        local url = "http://127.0.0.1:8080/webauthn/auth"
        ngx.req.set_header("X-Forwarded-Proto", ngx.var.scheme)
        ngx.req.set_header("Host", ngx.var.host)
        local res, err = h:request_uri(url, {method = "GET", headers = ngx.req.get_headers()})
        if err or not res or res.status ~= 200 then
            ngx.redirect("/webauthn/login?redirect_url=" .. ngx.var.request_uri .. "&default_username=" .. ngx.var.email)
            ngx.exit(ngx.HTTP_OK)
        end
    }
    # ...
}

location /webauthn/ {
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $host;
    proxy_pass http://127.0.0.1:8080;
}

Learn More

About

Proxy for enforcing webauthn authentication

Resources

Security policy

Stars

147 stars

Watchers

7 watching

Forks

Releases

Packages

Used by

Contributors

Languages