[Feature Request] add auth.method = "none" to allow frps plugins to be the sole authentication mechanism
Problem
When an HTTP login plugin is configured, frps calls the plugin first and then always runs the built-in VerifyLogin check afterward (server/service.go). There is no way to configure frps to skip the built-in check and delegate authentication entirely to the plugin.
This makes it impossible to implement the natural use case: a login plugin that validates a bearer token (e.g. a signed JWT) without also maintaining a pre-shared token on frps.
Concrete example
- frpc uses
auth.method = oidc+auth.oidc.tokenSource = execto fetch a signed JWT dynamically and send it asprivilege_key - A login plugin validates the JWT (checks signature, issuer, audience, claims)
- frps rejects the connection anyway because
VerifyLogincomputesMD5(server_token + timestamp)and it does not match the JWT string
As a workaround, I currently make my plugin rewrite privilege_key in its response to MD5("" + str(timestamp))
Proposed solution
Add auth.method = none to AuthServerConfig. When set, NewAuthVerifier returns AlwaysPassVerifier, making VerifyLogin a no-op. Authentication is then fully delegated to any registered login plugins.
The change is small and non-breaking:
pkg/config/v1/common.go: addAuthMethodNone AuthMethod = nonepkg/config/v1/validation/validation.go: addnonetoSupportedAuthMethodspkg/auth/auth.go: addcase v1.AuthMethodNone:authVerifier = AlwaysPassVerifierpkg/config/v1/server.go: keep default astokenso existing configs are unaffected
frps config usage:
[auth]
method = "none"
[[httpPlugins]]
name = "my-auth-plugin"
addr = "http://127.0.0.1:8080"
ops = ["Login"]
Why this is safe
A login plugin already has full control over whether a connection is accepted or rejected. VerifyLogin running afterward adds nothing when a login plugin is registered: the plugin is the gate. auth.method = none simply makes that explicit and removes the redundant check.
Affected area
- Docs
- User Experience
- Server Plugin
Source: fatedier/frp