[GH-ISSUE #4989] auth.token used for encryption in addition to authentication? #3932

Closed
opened 2026-05-05 14:30:22 -06:00 by gitea-mirror · 4 comments
Owner

Originally created by @caphrim007 on GitHub (Sep 20, 2025).
Original GitHub issue: https://github.com/fatedier/frp/issues/4989

Bug Description

I started using frpc/s with token authentication. My configuration looked like the following (in both)

auth.method = "token"
auth.token = "foobar"

I later switched to OIDC authentication but left the token stuff in there because I thought that FRP would treat these parameters conditionally. In other words, my updated config looked like this

frps

auth.method = "oidc"
auth.token = "foobar"
auth.oidc.issuer = "https://example-oidc-issuer.com/"
auth.oidc.audience = "https://oidc-audience.com/.default"

and

frpc

auth.method = "oidc"
auth.token = "foobar"

auth.oidc.clientID = "98692467-37de-409a-9fac-bb2585826f18" # Replace with OIDC client ID
auth.oidc.clientSecret = "oidc_secret"
auth.oidc.audience = "https://oidc-audience.com/.default"
auth.oidc.tokenEndpointURL = "https://example-oidc-endpoint.com/oauth2/v2.0/token"

The behavior I expected to see was that FRPc/s would ignore the auth.token values.

Instead, what I saw was what appeared to be an infinite loop of LoginInfos and clients closing connections.

When I looked deeper, I think what is occurring is that FRP uses auth.token for more than simply authentication.

The server encounters this code

https://github.com/fatedier/frp/blob/dev/server/control.go#L188

The value of ctlConnEncrypted comes from here I think

https://github.com/fatedier/frp/blob/dev/server/service.go#L595

which sets it to !internal.

The value of internal differs based on the Listener being handled. The Listeners I have are

and, I assume, this default one here

FRPc has similar connection encrypted logic here

My grok'ing of that handler setup is "internal is false, but !internal makes it true, ergo ctlConnEncrypted is true, ergo use encryption.".

When I looked into the docs on useEncryption, I dont see any mention of auth.token needing to be required. I do see this here

which says

// UseEncryption controls whether or not communication with the server will
// be encrypted. Encryption is done using the tokens supplied in the server
// and client configuration.

Which seems to imply that auth.token is used. So my leaving it in the frps.toml and was inadvertently making the server use it.

When I removed auth.token from either the frps.toml or frpc.toml (keeping it in the other), the behavior I mentioned of "infinite loop of re-logins and close connection" happened.

When I removed auth.token from both frpc.toml and frps.toml, I connected with OIDC as I expected.

Is this intended behavior?

I didn't see documentation specifying usage of the auth.token here

So I was surprised to find in the code its apparent re-usage outside of authentication.

What I have not tried doing yet is setting transport.useEncryption = true in the frpc.toml file's proxies. I suspect this might cause the client to now use the auth.token that I had kept in there, and since the server would be using it to begin with (by virtue of !internal) that the connection would now complete.

frpc Version

0.63.0

frps Version

0.63.0

System Architecture

linux/amd64

Configurations

frpc.toml

serverAddr = "foo.bar.local"
serverPort = 80

loginFailExit = true

log.to = "console"
log.level = "info"
log.maxDays = 3
log.disablePrintColor = false

auth.method = "oidc"
auth.token = "foobar"

auth.oidc.clientID = "clientid1"
auth.oidc.clientSecret = "secret1"
auth.oidc.tokenEndpointURL = "https://foo.bar.local/auth/oauth/token"

transport.poolCount = 0
transport.protocol = "websocket"
transport.connectServerLocalIP = ""
transport.tls.enable = false

udpPacketSize = 1500
metadatas.foo = "alice"

[[proxies]]
name = "web"
type = "http"
localIP = "127.0.0.1"
localPort = 4000
customDomains = ["web.local"]
metadatas.foo = "alice"
metadatas.bar = "bob"

frps.toml

    bindAddr = "0.0.0.0"
    bindPort = 7000

    auth.method = "oidc"
    auth.token = "foobar"
    auth.oidc.issuer = "http://oidc.foo.bar:8080/auth/oauth/token"
    auth.oidc.skipExpiryCheck = false
    auth.oidc.skipIssuerCheck = false

    log.to = "console"
    log.level = "trace"
    log.maxDays = 3

    vhostHTTPPort = 80

Logs

when the auth.token is set, the client logs will just spin emitting this sequence of messages

2025-09-19 19:12:09.391 [I] [server/service.go:511] start check TLS connection...
2025-09-19 19:12:09.454 [I] [server/service.go:582] [931c2e27aea2788] client login info: ip [http://foo.bar.local:80] version [0.63.0] hostname [] os [linux] arch [amd64]
2025-09-19 19:12:09.587 [I] [server/control.go:357] [931c2e27aea2788] client exit success
2025-09-19 19:12:09.632 [I] [server/service.go:511] start check TLS connection...
2025-09-19 19:12:09.685 [I] [server/service.go:582] [931c2e27aea2788] client login info: ip [http://foo.bar.local:80] version [0.63.0] hostname [] os [linux] arch [amd64]
2025-09-19 19:12:09.807 [I] [server/control.go:357] [931c2e27aea2788] client exit success
...
2025-09-19 19:12:12.491 [E] [server/service.go:430] failed to read message: message type error

I think the message type error is related to the client being unable to decrypt the encrypted message being sent from the server.

Steps to reproduce

...

Affected area

  • Docs
  • Installation
  • Performance and Scalability
  • Security
  • User Experience
  • Test and Release
  • Developer Infrastructure
  • Client Plugin
  • Server Plugin
  • Extensions
  • Others
Originally created by @caphrim007 on GitHub (Sep 20, 2025). Original GitHub issue: https://github.com/fatedier/frp/issues/4989 ### Bug Description I started using frpc/s with token authentication. My configuration looked like the following (in both) ``` auth.method = "token" auth.token = "foobar" ``` I later switched to OIDC authentication but left the token stuff in there because I thought that FRP would treat these parameters conditionally. In other words, my updated config looked like this **frps** ``` auth.method = "oidc" auth.token = "foobar" auth.oidc.issuer = "https://example-oidc-issuer.com/" auth.oidc.audience = "https://oidc-audience.com/.default" ``` and **frpc** ``` auth.method = "oidc" auth.token = "foobar" auth.oidc.clientID = "98692467-37de-409a-9fac-bb2585826f18" # Replace with OIDC client ID auth.oidc.clientSecret = "oidc_secret" auth.oidc.audience = "https://oidc-audience.com/.default" auth.oidc.tokenEndpointURL = "https://example-oidc-endpoint.com/oauth2/v2.0/token" ``` The behavior I expected to see was that FRPc/s would ignore the `auth.token` values. Instead, what I saw was what appeared to be an infinite loop of LoginInfos and clients closing connections. When I looked deeper, I think what is occurring is that FRP uses auth.token for more than simply authentication. The server encounters this code https://github.com/fatedier/frp/blob/dev/server/control.go#L188 The value of `ctlConnEncrypted` comes from here I think https://github.com/fatedier/frp/blob/dev/server/service.go#L595 which sets it to `!internal`. The value of `internal` differs based on the Listener being handled. The Listeners I have are * https://github.com/fatedier/frp/blob/dev/server/service.go#L365 * https://github.com/fatedier/frp/blob/dev/server/service.go#L366 and, I assume, this default one here * https://github.com/fatedier/frp/blob/dev/server/service.go#L376 FRPc has similar connection encrypted logic here * https://github.com/fatedier/frp/blob/dev/client/control.go#L93 My grok'ing of that handler setup is "internal is false, but `!internal` makes it true, ergo `ctlConnEncrypted` is true, ergo use encryption.". When I looked into the docs on useEncryption, I dont see any mention of auth.token needing to be required. I do see this here * https://github.com/fatedier/frp/blob/dev/pkg/config/v1/proxy.go#L32 which says ``` // UseEncryption controls whether or not communication with the server will // be encrypted. Encryption is done using the tokens supplied in the server // and client configuration. ``` Which seems to imply that `auth.token` is used. So my leaving it in the frps.toml and was inadvertently making the server use it. When I removed auth.token from either the frps.toml or frpc.toml (keeping it in the other), the behavior I mentioned of "infinite loop of re-logins and close connection" happened. When I removed auth.token from both frpc.toml and frps.toml, I connected with OIDC as I expected. Is this intended behavior? I didn't see documentation specifying usage of the auth.token here * https://github.com/fatedier/frp?tab=readme-ov-file#encryption-and-compression So I was surprised to find in the code its apparent re-usage outside of authentication. What I have **not** tried doing yet is setting `transport.useEncryption = true` in the frpc.toml file's [[proxies]]. I suspect this might cause the client to now use the auth.token that I had kept in there, and since the server would be using it to begin with (by virtue of `!internal`) that the connection would now complete. ### frpc Version 0.63.0 ### frps Version 0.63.0 ### System Architecture linux/amd64 ### Configurations frpc.toml ``` serverAddr = "foo.bar.local" serverPort = 80 loginFailExit = true log.to = "console" log.level = "info" log.maxDays = 3 log.disablePrintColor = false auth.method = "oidc" auth.token = "foobar" auth.oidc.clientID = "clientid1" auth.oidc.clientSecret = "secret1" auth.oidc.tokenEndpointURL = "https://foo.bar.local/auth/oauth/token" transport.poolCount = 0 transport.protocol = "websocket" transport.connectServerLocalIP = "" transport.tls.enable = false udpPacketSize = 1500 metadatas.foo = "alice" [[proxies]] name = "web" type = "http" localIP = "127.0.0.1" localPort = 4000 customDomains = ["web.local"] metadatas.foo = "alice" metadatas.bar = "bob" ``` frps.toml ``` bindAddr = "0.0.0.0" bindPort = 7000 auth.method = "oidc" auth.token = "foobar" auth.oidc.issuer = "http://oidc.foo.bar:8080/auth/oauth/token" auth.oidc.skipExpiryCheck = false auth.oidc.skipIssuerCheck = false log.to = "console" log.level = "trace" log.maxDays = 3 vhostHTTPPort = 80 ``` ### Logs when the auth.token is set, the client logs will just spin emitting this sequence of messages ``` 2025-09-19 19:12:09.391 [I] [server/service.go:511] start check TLS connection... 2025-09-19 19:12:09.454 [I] [server/service.go:582] [931c2e27aea2788] client login info: ip [http://foo.bar.local:80] version [0.63.0] hostname [] os [linux] arch [amd64] 2025-09-19 19:12:09.587 [I] [server/control.go:357] [931c2e27aea2788] client exit success 2025-09-19 19:12:09.632 [I] [server/service.go:511] start check TLS connection... 2025-09-19 19:12:09.685 [I] [server/service.go:582] [931c2e27aea2788] client login info: ip [http://foo.bar.local:80] version [0.63.0] hostname [] os [linux] arch [amd64] 2025-09-19 19:12:09.807 [I] [server/control.go:357] [931c2e27aea2788] client exit success ... 2025-09-19 19:12:12.491 [E] [server/service.go:430] failed to read message: message type error ``` I think the `message type error` is related to the client being unable to decrypt the encrypted message being sent from the server. ### Steps to reproduce 1. 2. 3. ... ### Affected area - [x] Docs - [x] Installation - [ ] Performance and Scalability - [ ] Security - [x] User Experience - [ ] Test and Release - [ ] Developer Infrastructure - [ ] Client Plugin - [ ] Server Plugin - [ ] Extensions - [ ] Others
Author
Owner

@fatedier commented on GitHub (Sep 21, 2025):

This is the expected behavior. auth.token must always be consistent between frps and frpc. When you switch to another authentication method, you can set this parameter to an empty value to avoid conflicts.

<!-- gh-comment-id:3315991966 --> @fatedier commented on GitHub (Sep 21, 2025): This is the expected behavior. auth.token must always be consistent between frps and frpc. When you switch to another authentication method, you can set this parameter to an empty value to avoid conflicts.
Author
Owner

@caphrim007 commented on GitHub (Sep 22, 2025):

@fatedier thanks for the clarification. Would you accept a (docs) PR that clarifies the usage of the auth.token value (if it is set in the client or server) under the section here https://github.com/fatedier/frp?tab=readme-ov-file#encryption-and-compression ?

<!-- gh-comment-id:3319827697 --> @caphrim007 commented on GitHub (Sep 22, 2025): @fatedier thanks for the clarification. Would you accept a (docs) PR that clarifies the usage of the auth.token value (if it is set in the client or server) under the section here https://github.com/fatedier/frp?tab=readme-ov-file#encryption-and-compression ?
Author
Owner

@fatedier commented on GitHub (Sep 22, 2025):

In fact, since frpc and frps mainly rely on TLS for encrypted transmission, transport.useEncryption is no longer recommended. For now, the documentation does not intend to provide more detailed explanations.

<!-- gh-comment-id:3319895295 --> @fatedier commented on GitHub (Sep 22, 2025): In fact, since frpc and frps mainly rely on TLS for encrypted transmission, transport.useEncryption is no longer recommended. For now, the documentation does not intend to provide more detailed explanations.
Author
Owner

@caphrim007 commented on GitHub (Sep 22, 2025):

ok. understood. thanks for the feedback

<!-- gh-comment-id:3319920851 --> @caphrim007 commented on GitHub (Sep 22, 2025): ok. understood. thanks for the feedback
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/frp#3932
No description provided.