From 85c6bf2e27a1c97ba646e32ee64acd752862a299 Mon Sep 17 00:00:00 2001 From: riccardom Date: Fri, 25 Sep 2026 13:16:57 +0200 Subject: [PATCH] [client] Provision the peer identity on the iOS login path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Key generation used to happen inside apply(), so a config loaded from JSON with no keys got them in memory on the way in, the login worked, and the app stored the result. This branch moved generation into EnsureIdentity, and nothing in the iOS SDK called it. The consequence lands on the flow the mobile logout sets up: logout clears both keys in place so the next login registers a new peer. The app then hands that keyless JSON to Auth.SetConfigFromJSON, and the login calls auth.NewAuth with an empty WireGuard key, which fails on key size before the SSO flow starts — the user cannot sign back in. Auth.setBaseConfig now provisions, which covers both entry points (NewAuth and SetConfigFromJSON). It mints on the base config, the one GetConfigJSON returns for the caller to persist, and writes it to disk itself when the profile has a file — non-atomically, like NewAuth's own write, since the tvOS App Group sandbox blocks temp-file-and-rename. Not covered by a test: the package builds only under GOOS=ios, which the test jobs do not run. Verified by building and vetting for GOOS=ios/arm64. Reported by pappz in review. --- client/ios/NetBirdSDK/login.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/client/ios/NetBirdSDK/login.go b/client/ios/NetBirdSDK/login.go index 0dfff620e..6a9a6d3d0 100644 --- a/client/ios/NetBirdSDK/login.go +++ b/client/ios/NetBirdSDK/login.go @@ -379,6 +379,35 @@ func (a *Auth) SetConfigFromJSON(jsonStr string) error { } func (a *Auth) setBaseConfig(base *profilemanager.Config) error { + // A logged-out profile carries no keys: the mobile logout clears them in + // place so the next login registers a new peer instead of resurrecting the + // old one. This is that login, and auth.NewAuth parses the WireGuard key + // before the SSO flow even starts, so an absent identity fails the login on + // key size rather than asking the user to sign in. + // + // Minted on the base config, which is the one GetConfigJSON hands back for + // the caller to store — the overlaid copy below is runtime-only. + generated, err := base.EnsureIdentity() + if err != nil { + return fmt.Errorf("ensure profile identity: %w", err) + } + if generated { + if a.cfgPath != "" { + // Non-atomic, like NewAuth's own write: the tvOS App Group sandbox + // blocks the temp-file-and-rename an atomic write needs. + if err := profilemanager.DirectWriteOutConfig(a.cfgPath, base); err != nil { + return fmt.Errorf("write out profile config: %w", err) + } + } else { + // No file to write to — this is the tvOS path, where the profile + // lives in the caller's own store. It persists the new identity by + // calling GetConfigJSON once the login completes; until then the + // keys exist only here, and a login that never completes leaves + // nothing behind. + log.Infof("provisioned a peer identity for a config with no file on disk") + } + } + overlaid, err := copyConfig(base) if err != nil { return err