mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-23 07:09:08 +02:00
[client] Extract SSH JWT cache into shared jwtcache package
Move the daemon's memguard-backed JWT token cache from client/server into client/ssh/jwtcache so it can be reused outside the daemon process. The TTL derivation from Config.SSHJWTCacheTTL (nil=default, 0=disabled) moves into jwtcache.ResolveTTL. Wire the cache into the iOS SDK's SSH client: iOS has no daemon to delegate caching to, so without it every reconnect forced the user through the browser OAuth device-code flow. The cache lives on the long-lived Client (the app creates a new SSHClient per session) and uses the same config-driven TTL semantics as the daemon.
This commit is contained in:
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/netbirdio/netbird/client/internal/listener"
|
||||
"github.com/netbirdio/netbird/client/internal/peer"
|
||||
"github.com/netbirdio/netbird/client/internal/profilemanager"
|
||||
"github.com/netbirdio/netbird/client/ssh/jwtcache"
|
||||
"github.com/netbirdio/netbird/client/system"
|
||||
"github.com/netbirdio/netbird/formatter"
|
||||
"github.com/netbirdio/netbird/route"
|
||||
@@ -87,6 +88,11 @@ type Client struct {
|
||||
// config holds the active configuration once Run has loaded it. Consumed by
|
||||
// the in-app SSH client for the NetBird SSH key and the OAuth flow.
|
||||
config *profilemanager.Config
|
||||
|
||||
// sshJWTCache keeps the SSH JWT token between reconnects so the user is not
|
||||
// forced through the browser OAuth flow on every session. Lives on Client
|
||||
// (not SSHClient) because the app creates a new SSHClient per session.
|
||||
sshJWTCache *jwtcache.Cache
|
||||
}
|
||||
|
||||
// NewClient instantiate a new Client
|
||||
@@ -103,6 +109,7 @@ func NewClient(cfgFile, stateFile, cacheDir, logFilePath, deviceName string, osV
|
||||
ctxCancelLock: &sync.Mutex{},
|
||||
networkChangeListener: networkChangeListener,
|
||||
dnsManager: dnsManager,
|
||||
sshJWTCache: jwtcache.New(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/netbirdio/netbird/client/internal/profilemanager"
|
||||
nbssh "github.com/netbirdio/netbird/client/ssh"
|
||||
"github.com/netbirdio/netbird/client/ssh/detection"
|
||||
"github.com/netbirdio/netbird/client/ssh/jwtcache"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -293,6 +294,14 @@ func (s *SSHClient) buildAuth(cfg *profilemanager.Config, engine *internal.Engin
|
||||
}
|
||||
|
||||
func (s *SSHClient) requestJWTToken(cfg *profilemanager.Config) (string, error) {
|
||||
// Reuse a cached token so the user is not forced through the browser OAuth
|
||||
// flow on every reconnect. TTL comes from cfg.SSHJWTCacheTTL, same as the
|
||||
// daemon's cache; unset/0 disables caching.
|
||||
if token, ok := s.nb.sshJWTCache.Get(); ok {
|
||||
log.Debug("SSH: reusing cached JWT token")
|
||||
return token, nil
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
urlOpener := s.urlOpener
|
||||
s.mu.Unlock()
|
||||
@@ -324,6 +333,10 @@ func (s *SSHClient) requestJWTToken(cfg *profilemanager.Config) (string, error)
|
||||
if token == "" {
|
||||
return "", errors.New("empty token returned by IdP")
|
||||
}
|
||||
|
||||
if ttl := jwtcache.ResolveTTL(cfg.SSHJWTCacheTTL); ttl > 0 {
|
||||
s.nb.sshJWTCache.Store(token, ttl)
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user