From df843368ceb5eb6cd38592662bc74a601441b76b Mon Sep 17 00:00:00 2001 From: Sylvain Bettinelli Date: Mon, 3 Aug 2026 15:21:28 +0000 Subject: [PATCH] fix(ios): injecte le cookie d'auth dans le store de la WKWebView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AppDelegate écrivait dans HTTPCookieStorage.shared, qui est le store d'URLSession — pas celui que lit la WKWebView (WKWebsiteDataStore). Ça fonctionnait jusqu'en mai parce que Capacitor recopiait alors les cookies au démarrage ; ce n'est plus le cas, et l'app retombait sur l'écran de login malgré un token valide (constaté sur device le 2026-08-03). MainViewController.viewDidLoad injecte désormais dans le store de la WebView, puis recharge une fois pour rejouer la première requête avec le cookie. Pas de boucle : au passage suivant le cookie existe et on sort avant. L'injection AppDelegate est conservée : elle sert aux appels natifs URLSession. Co-Authored-By: Claude Opus 5 --- ios/App/App/MainViewController.swift | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/ios/App/App/MainViewController.swift b/ios/App/App/MainViewController.swift index 933ed2b..3cb0ad5 100644 --- a/ios/App/App/MainViewController.swift +++ b/ios/App/App/MainViewController.swift @@ -6,6 +6,7 @@ import UIKit import Capacitor +import WebKit class MainViewController: CAPBridgeViewController { override func capacitorDidLoad() { @@ -37,8 +38,50 @@ class MainViewController: CAPBridgeViewController { bridge?.registerPluginInstance(CoachRoutineBridgePlugin()) } + /// Injecte le cookie d'auth dans le magasin de la WKWebView. + /// + /// ⚠️ `AppDelegate.injectCoachAuthCookie()` écrit dans + /// `HTTPCookieStorage.shared` — c'est le store d'URLSession, PAS celui que + /// lit la WKWebView. Ça a marché jusqu'en mai parce que Capacitor recopiait + /// alors les cookies au démarrage ; ce n'est plus le cas, d'où l'écran de + /// login qui réapparaissait (constaté sur device le 2026-08-03). + /// + /// Les deux injections sont conservées : `HTTPCookieStorage.shared` reste + /// utile aux appels natifs via URLSession. + private func injectAuthCookieIntoWebView() { + let token = CoachAuth.kCoachWebToken + guard !token.isEmpty, token != "REPLACE_ME", let webView = self.webView else { return } + + let store = webView.configuration.websiteDataStore.httpCookieStore + store.getAllCookies { cookies in + // Ne PAS écraser une session per-user existante (login Apple/Google). + if cookies.contains(where: { + $0.name == "coach_web_token" && $0.domain.contains("coach.hypnotruck.ch") + }) { return } + + let oneYear: TimeInterval = 60 * 60 * 24 * 365 + guard let cookie = HTTPCookie(properties: [ + .name: "coach_web_token", + .value: token, + .domain: "coach.hypnotruck.ch", + .path: "/", + .secure: true, + .expires: Date(timeIntervalSinceNow: oneYear), + ]) else { return } + + store.setCookie(cookie) { + // La première requête est déjà partie sans cookie (on a atterri + // sur /login) : il faut recharger pour la rejouer avec. + // Pas de boucle possible — au prochain passage le cookie existe + // et on sort au `return` ci-dessus. + DispatchQueue.main.async { webView.reload() } + } + } + } + override func viewDidLoad() { super.viewDidLoad() + injectAuthCookieIntoWebView() // Force le background noir sur tous les niveaux pour éliminer la // bande blanche du bounce iOS WKWebView (cause : scrollView.backgroundColor // par défaut blanc, exposé lors de l'overscroll). Aucun CSS web ne peut